Forked from xebecnan/lundump_lua53_load_x32_bytecode_on_x64.c
Last active
September 12, 2018 02:18
-
-
Save kentkrantz/d90eac2c6885218b0ef1373fc5057fc8 to your computer and use it in GitHub Desktop.
lua5.3.5 compatible 32bit and 64bit bytecode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| ** $Id: lundump.c,v 2.44.1.1 2017/04/19 17:20:42 roberto Exp $ | |
| ** load precompiled Lua chunks | |
| ** See Copyright Notice in lua.h | |
| */ | |
| #define lundump_c | |
| #define LUA_CORE | |
| #include "lprefix.h" | |
| #include <string.h> | |
| #include "lua.h" | |
| #include "ldebug.h" | |
| #include "ldo.h" | |
| #include "lfunc.h" | |
| #include "lmem.h" | |
| #include "lobject.h" | |
| #include "lstring.h" | |
| #include "lundump.h" | |
| #include "lzio.h" | |
| #if !defined(luai_verifycode) | |
| #define luai_verifycode(L,b,f) /* empty */ | |
| #endif | |
| /* | |
| typedef struct { | |
| lua_State *L; | |
| ZIO *Z; | |
| const char *name; | |
| } LoadState; | |
| */ | |
| //--------------------------------------- | |
| // https://gist.github.com/xebecnan/efa0b60d70e2dbf49b8a | |
| typedef struct { | |
| lua_State *L; | |
| ZIO *Z; | |
| Mbuffer *b; | |
| const char *name; | |
| lu_byte load_size_t_size; | |
| lu_byte load_size_t_offset; | |
| } LoadState; | |
| typedef union { | |
| lua_Integer a; | |
| lu_byte b[sizeof(lua_Integer)]; | |
| } IntOrBytes; | |
| #define ST_SIZE sizeof(size_t) | |
| //--------------------------------------- | |
| static l_noret error(LoadState *S, const char *why) { | |
| luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why); | |
| luaD_throw(S->L, LUA_ERRSYNTAX); | |
| } | |
| /* | |
| ** All high-level loads go through LoadVector; you can change it to | |
| ** adapt to the endianness of the input | |
| */ | |
| #define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0])) | |
| static void LoadBlock (LoadState *S, void *b, size_t size) { | |
| if (luaZ_read(S->Z, b, size) != 0) | |
| error(S, "truncated"); | |
| } | |
| #define LoadVar(S,x) LoadVector(S,&x,1) | |
| static lu_byte LoadByte (LoadState *S) { | |
| lu_byte x; | |
| LoadVar(S, x); | |
| return x; | |
| } | |
| static int LoadInt (LoadState *S) { | |
| int x; | |
| LoadVar(S, x); | |
| return x; | |
| } | |
| static lua_Number LoadNumber (LoadState *S) { | |
| lua_Number x; | |
| LoadVar(S, x); | |
| return x; | |
| } | |
| static lua_Integer LoadInteger (LoadState *S) { | |
| lua_Integer x; | |
| LoadVar(S, x); | |
| return x; | |
| } | |
| /* | |
| static TString *LoadString (LoadState *S) { | |
| size_t size = LoadByte(S); | |
| if (size == 0xFF) | |
| LoadVar(S, size); | |
| if (size == 0) | |
| return NULL; | |
| else if (--size <= LUAI_MAXSHORTLEN) { // short string? | |
| char buff[LUAI_MAXSHORTLEN]; | |
| LoadVector(S, buff, size); | |
| return luaS_newlstr(S->L, buff, size); | |
| } | |
| else { // long string | |
| TString *ts = luaS_createlngstrobj(S->L, size); | |
| LoadVector(S, getstr(ts), size); // load directly in final place | |
| return ts; | |
| } | |
| }*/ | |
| //--------------------------------------- | |
| static size_t LoadSize(LoadState* S) { | |
| union { | |
| lu_byte b[ST_SIZE]; | |
| size_t sz; | |
| } v; | |
| memset(&v, 0, sizeof(v)); | |
| LoadBlock(S, &v.b[S->load_size_t_offset], S->load_size_t_size); | |
| return v.sz; | |
| } | |
| /* | |
| static TString *LoadString (LoadState *S) { | |
| size_t size = LoadByte(S); | |
| if (size == 0xFF) { | |
| // LoadVar(S, size); | |
| size = LoadSize(S); | |
| } | |
| if (size == 0) | |
| return NULL; | |
| else { | |
| char *s = luaZ_openspace(S->L, S->b, --size); | |
| LoadVector(S, s, size); | |
| return luaS_newlstr(S->L, s, size); | |
| } | |
| }*/ | |
| static TString *LoadString (LoadState *S) { | |
| size_t size = LoadByte(S); | |
| if (size == 0xFF) | |
| // LoadVar(S, size); | |
| size = LoadSize(S); | |
| if (size == 0) | |
| return NULL; | |
| else if (--size <= LUAI_MAXSHORTLEN) { // short string? | |
| char buff[LUAI_MAXSHORTLEN]; | |
| LoadVector(S, buff, size); | |
| return luaS_newlstr(S->L, buff, size); | |
| } | |
| else { // long string | |
| TString *ts = luaS_createlngstrobj(S->L, size); | |
| LoadVector(S, getstr(ts), size); // load directly in final place | |
| return ts; | |
| } | |
| } | |
| //--------------------------------------- | |
| static void LoadCode (LoadState *S, Proto *f) { | |
| int n = LoadInt(S); | |
| f->code = luaM_newvector(S->L, n, Instruction); | |
| f->sizecode = n; | |
| LoadVector(S, f->code, n); | |
| } | |
| static void LoadFunction(LoadState *S, Proto *f, TString *psource); | |
| static void LoadConstants (LoadState *S, Proto *f) { | |
| int i; | |
| int n = LoadInt(S); | |
| f->k = luaM_newvector(S->L, n, TValue); | |
| f->sizek = n; | |
| for (i = 0; i < n; i++) | |
| setnilvalue(&f->k[i]); | |
| for (i = 0; i < n; i++) { | |
| TValue *o = &f->k[i]; | |
| int t = LoadByte(S); | |
| switch (t) { | |
| case LUA_TNIL: | |
| setnilvalue(o); | |
| break; | |
| case LUA_TBOOLEAN: | |
| setbvalue(o, LoadByte(S)); | |
| break; | |
| case LUA_TNUMFLT: | |
| setfltvalue(o, LoadNumber(S)); | |
| break; | |
| case LUA_TNUMINT: | |
| setivalue(o, LoadInteger(S)); | |
| break; | |
| case LUA_TSHRSTR: | |
| case LUA_TLNGSTR: | |
| setsvalue2n(S->L, o, LoadString(S)); | |
| break; | |
| default: | |
| lua_assert(0); | |
| } | |
| } | |
| } | |
| static void LoadProtos (LoadState *S, Proto *f) { | |
| int i; | |
| int n = LoadInt(S); | |
| f->p = luaM_newvector(S->L, n, Proto *); | |
| f->sizep = n; | |
| for (i = 0; i < n; i++) | |
| f->p[i] = NULL; | |
| for (i = 0; i < n; i++) { | |
| f->p[i] = luaF_newproto(S->L); | |
| LoadFunction(S, f->p[i], f->source); | |
| } | |
| } | |
| static void LoadUpvalues (LoadState *S, Proto *f) { | |
| int i, n; | |
| n = LoadInt(S); | |
| f->upvalues = luaM_newvector(S->L, n, Upvaldesc); | |
| f->sizeupvalues = n; | |
| for (i = 0; i < n; i++) | |
| f->upvalues[i].name = NULL; | |
| for (i = 0; i < n; i++) { | |
| f->upvalues[i].instack = LoadByte(S); | |
| f->upvalues[i].idx = LoadByte(S); | |
| } | |
| } | |
| static void LoadDebug (LoadState *S, Proto *f) { | |
| int i, n; | |
| n = LoadInt(S); | |
| f->lineinfo = luaM_newvector(S->L, n, int); | |
| f->sizelineinfo = n; | |
| LoadVector(S, f->lineinfo, n); | |
| n = LoadInt(S); | |
| f->locvars = luaM_newvector(S->L, n, LocVar); | |
| f->sizelocvars = n; | |
| for (i = 0; i < n; i++) | |
| f->locvars[i].varname = NULL; | |
| for (i = 0; i < n; i++) { | |
| f->locvars[i].varname = LoadString(S); | |
| f->locvars[i].startpc = LoadInt(S); | |
| f->locvars[i].endpc = LoadInt(S); | |
| } | |
| n = LoadInt(S); | |
| for (i = 0; i < n; i++) | |
| f->upvalues[i].name = LoadString(S); | |
| } | |
| static void LoadFunction (LoadState *S, Proto *f, TString *psource) { | |
| f->source = LoadString(S); | |
| if (f->source == NULL) /* no source in dump? */ | |
| f->source = psource; /* reuse parent's source */ | |
| f->linedefined = LoadInt(S); | |
| f->lastlinedefined = LoadInt(S); | |
| f->numparams = LoadByte(S); | |
| f->is_vararg = LoadByte(S); | |
| f->maxstacksize = LoadByte(S); | |
| LoadCode(S, f); | |
| LoadConstants(S, f); | |
| LoadUpvalues(S, f); | |
| LoadProtos(S, f); | |
| LoadDebug(S, f); | |
| } | |
| static void checkliteral (LoadState *S, const char *s, const char *msg) { | |
| char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ | |
| size_t len = strlen(s); | |
| LoadVector(S, buff, len); | |
| if (memcmp(s, buff, len) != 0) | |
| error(S, msg); | |
| } | |
| static void fchecksize (LoadState *S, size_t size, const char *tname) { | |
| if (LoadByte(S) != size) | |
| error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname)); | |
| } | |
| #define checksize(S,t) fchecksize(S,sizeof(t),#t) | |
| /* | |
| static void checkHeader (LoadState *S) { | |
| checkliteral(S, LUA_SIGNATURE + 1, "not a"); // 1st char already checked | |
| if (LoadByte(S) != LUAC_VERSION) | |
| error(S, "version mismatch in"); | |
| if (LoadByte(S) != LUAC_FORMAT) | |
| error(S, "format mismatch in"); | |
| checkliteral(S, LUAC_DATA, "corrupted"); | |
| checksize(S, int); | |
| checksize(S, size_t); | |
| checksize(S, Instruction); | |
| checksize(S, lua_Integer); | |
| checksize(S, lua_Number); | |
| if (LoadInteger(S) != LUAC_INT) | |
| error(S, "endianness mismatch in"); | |
| if (LoadNumber(S) != LUAC_NUM) | |
| error(S, "float format mismatch in"); | |
| }*/ | |
| //--------------------------------------- | |
| static void checkHeader (LoadState *S) { | |
| checkliteral(S, LUA_SIGNATURE + 1, "not a"); /* 1st char already checked */ | |
| if (LoadByte(S) != LUAC_VERSION) | |
| error(S, "version mismatch in"); | |
| if (LoadByte(S) != LUAC_FORMAT) | |
| error(S, "format mismatch in"); | |
| checkliteral(S, LUAC_DATA, "corrupted"); | |
| checksize(S, int); | |
| /* supprt run x32 bytes on x64 arch */ | |
| /* checksize(S, size_t); */ | |
| S->load_size_t_size = LoadByte(S); | |
| checksize(S, Instruction); | |
| checksize(S, lua_Integer); | |
| checksize(S, lua_Number); | |
| /* supprt run x32 bytes on x64 arch */ | |
| IntOrBytes i = (IntOrBytes)LoadInteger(S); | |
| lu_byte b = (lu_byte)LUAC_INT; | |
| int is_little_endian = (i.b[0] == b) ? 1 : 0; | |
| S->load_size_t_offset = is_little_endian ? 0 : (ST_SIZE - S->load_size_t_size); | |
| if (i.a != LUAC_INT) | |
| error(S, "endianness mismatch in"); | |
| if (LoadNumber(S) != LUAC_NUM) | |
| error(S, "float format mismatch in"); | |
| } | |
| //--------------------------------------- | |
| /* | |
| ** load precompiled chunk | |
| */ | |
| LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { | |
| LoadState S; | |
| LClosure *cl; | |
| if (*name == '@' || *name == '=') | |
| S.name = name + 1; | |
| else if (*name == LUA_SIGNATURE[0]) | |
| S.name = "binary string"; | |
| else | |
| S.name = name; | |
| S.L = L; | |
| S.Z = Z; | |
| checkHeader(&S); | |
| cl = luaF_newLclosure(L, LoadByte(&S)); | |
| setclLvalue(L, L->top, cl); | |
| luaD_inctop(L); | |
| cl->p = luaF_newproto(L); | |
| LoadFunction(&S, cl->p, NULL); | |
| lua_assert(cl->nupvalues == cl->p->sizeupvalues); | |
| luai_verifycode(L, buff, cl->p); | |
| return cl; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment