From 981fddea022b6cad7768223353b4e7386080c271 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 14 Jan 1998 13:49:01 -0200 Subject: module to load bytecodes from files. --- lundump.c | 272 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lundump.h | 27 ++++++ undump.c | 318 -------------------------------------------------------------- undump.h | 30 ------ 4 files changed, 299 insertions(+), 348 deletions(-) create mode 100644 lundump.c create mode 100644 lundump.h delete mode 100644 undump.c delete mode 100644 undump.h diff --git a/lundump.c b/lundump.c new file mode 100644 index 00000000..32d7359a --- /dev/null +++ b/lundump.c @@ -0,0 +1,272 @@ +/* +** $Id: lundump.c,v 1.4 1998/01/13 20:05:24 lhf Exp $ +** load bytecodes from files +** See Copyright Notice in lua.h +*/ + +#include +#include "lauxlib.h" +#include "lfunc.h" +#include "lmem.h" +#include "lstring.h" +#include "lundump.h" + +typedef struct { + ZIO* Z; + int SwapNumber; + int LoadFloat; +} Sundump; + +static void unexpectedEOZ(ZIO* Z) +{ + luaL_verror("unexpected end of binary file %s",Z->name); +} + +static int ezgetc(ZIO* Z) +{ + int c=zgetc(Z); + if (c==EOZ) unexpectedEOZ(Z); + return c; +} + +static int ezread(ZIO* Z, void* b, int n) +{ + int r=zread(Z,b,n); + if (r!=0) unexpectedEOZ(Z); + return r; +} + +static int LoadWord(ZIO* Z) +{ + int hi=ezgetc(Z); + int lo=ezgetc(Z); + return (hi<<8)|lo; +} + +static void* LoadBlock(int size, ZIO* Z) +{ + void* b=luaM_malloc(size); + ezread(Z,b,size); + return b; +} + +static int LoadSize(ZIO* Z) +{ + int hi=LoadWord(Z); + int lo=LoadWord(Z); + int s=(hi<<16)|lo; + if (hi!=0 && s==lo) + luaL_verror("code too long (%ld bytes)",(hi<<16)|(long)lo); + return s; +} + +static char* LoadString(ZIO* Z) +{ + int size=LoadWord(Z); + if (size==0) + return NULL; + else + { + char* b=luaL_openspace(size); + ezread(Z,b,size); + return b; + } +} + +static TaggedString* LoadTString(ZIO* Z) +{ + char* s=LoadString(Z); + return (s==NULL) ? NULL : luaS_new(s); +} + +static void SwapFloat(float* f) +{ + Byte* p=(Byte*)f; + Byte* q=p+sizeof(float)-1; + Byte t; + t=*p; *p++=*q; *q--=t; + t=*p; *p++=*q; *q--=t; +} + +static void SwapDouble(double* f) +{ + Byte* p=(Byte*)f; + Byte* q=p+sizeof(double)-1; + Byte t; + t=*p; *p++=*q; *q--=t; + t=*p; *p++=*q; *q--=t; + t=*p; *p++=*q; *q--=t; + t=*p; *p++=*q; *q--=t; +} + +static real LoadNumber(Sundump* S) +{ + if (S->LoadFloat) + { + float f; + ezread(S->Z,&f,sizeof(f)); + if (S->SwapNumber) SwapFloat(&f); + return f; + } + else + { + double f; + ezread(S->Z,&f,sizeof(f)); + if (S->SwapNumber) SwapDouble(&f); + return f; + } +} + +static void LoadLocals(TProtoFunc* tf, ZIO* Z) +{ + int i,n=LoadWord(Z); + if (n==0) return; + tf->locvars=luaM_newvector(n+1,LocVar); + for (i=0; ilocvars[i].line=LoadWord(Z); + tf->locvars[i].varname=LoadTString(Z); + } + tf->locvars[i].line=-1; /* flag end of vector */ + tf->locvars[i].varname=NULL; +} + +static void LoadConstants(TProtoFunc* tf, Sundump* S) +{ + int i,n=LoadWord(S->Z); + tf->nconsts=n; + if (n==0) return; + tf->consts=luaM_newvector(n,TObject); + for (i=0; iconsts+i; + int c=ezgetc(S->Z); + switch (c) + { + case ID_NUM: + ttype(o)=LUA_T_NUMBER; + nvalue(o)=LoadNumber(S); + break; + case ID_STR: + ttype(o)=LUA_T_STRING; + tsvalue(o)=LoadTString(S->Z); + break; + case ID_FUN: + ttype(o)=LUA_T_PROTO; + tfvalue(o)=NULL; + break; +#ifdef DEBUG + default: /* cannot happen */ + luaL_verror("internal error in LoadConstants: " + "bad constant #%d type=%d ('%c')\n",i,c,c); + break; +#endif + } + } +} + +static TProtoFunc* LoadFunction(Sundump* S); + +static void LoadFunctions(TProtoFunc* tf, Sundump* S) +{ + while (zgetc(S->Z)==ID_FUNCTION) + { + int i=LoadWord(S->Z); + TProtoFunc* t=LoadFunction(S); + TObject* o=tf->consts+i; + tfvalue(o)=t; + } +} + +static TProtoFunc* LoadFunction(Sundump* S) +{ + ZIO* Z=S->Z; + TProtoFunc* tf=luaF_newproto(); + tf->lineDefined=LoadWord(Z); + tf->fileName=LoadTString(Z); + tf->code=LoadBlock(LoadSize(Z),Z); + LoadConstants(tf,S); + LoadLocals(tf,Z); + LoadFunctions(tf,S); + return tf; +} + +static void LoadSignature(ZIO* Z) +{ + char* s=SIGNATURE; + while (*s!=0 && ezgetc(Z)==*s) + ++s; + if (*s!=0) luaL_verror("bad signature in binary file %s",Z->name); +} + +static void LoadHeader(Sundump* S) +{ + ZIO* Z=S->Z; + int version,sizeofR; + LoadSignature(Z); + version=ezgetc(Z); + if (version>VERSION) + luaL_verror( + "binary file %s too new: version=0x%02x; expected at most 0x%02x", + Z->name,version,VERSION); + if (version<0x31) /* major change in 3.1 */ + luaL_verror( + "binary file %s too old: version=0x%02x; expected at least 0x%02x", + Z->name,version,0x31); + sizeofR=ezgetc(Z); /* test float representation */ + if (sizeofR==sizeof(float)) + { + float f,tf=TEST_FLOAT; + ezread(Z,&f,sizeof(f)); + if (f!=tf) + { + SwapFloat(&f); + if (f!=tf) + luaL_verror("unknown float representation in binary file %s",Z->name); + S->SwapNumber=1; + } + S->LoadFloat=1; + } + else if (sizeofR==sizeof(double)) + { + double f,tf=TEST_FLOAT; + ezread(Z,&f,sizeof(f)); + if (f!=tf) + { + SwapDouble(&f); + if (f!=tf) + luaL_verror("unknown float representation in binary file %s",Z->name); + S->SwapNumber=1; + } + S->LoadFloat=0; + } + else + luaL_verror( + "floats in binary file %s have %d bytes; " + "expected %d (float) or %d (double)", + Z->name,sizeofR,sizeof(float),sizeof(double)); +} + +static TProtoFunc* LoadChunk(Sundump* S) +{ + LoadHeader(S); + return LoadFunction(S); +} + +/* +** load one chunk from a file or buffer +** return main if ok and NULL at EOF +*/ +TProtoFunc* luaU_undump1(ZIO* Z) +{ + int c=zgetc(Z); + Sundump S; + S.Z=Z; + S.SwapNumber=0; + S.LoadFloat=1; + if (c==ID_CHUNK) + return LoadChunk(&S); + else if (c!=EOZ) + luaL_verror("%s is not a lua binary file",Z->name); + return NULL; +} diff --git a/lundump.h b/lundump.h new file mode 100644 index 00000000..ea9e975c --- /dev/null +++ b/lundump.h @@ -0,0 +1,27 @@ +/* +** $Id: lundump.h,v 1.4 1998/01/13 20:05:24 lhf Exp $ +** load pre-compiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#ifndef lundump_h +#define lundump_h + +#include "lobject.h" +#include "lzio.h" + +#define ID_CHUNK 27 /* ESC */ +#define ID_FUNCTION '#' +#define ID_END '$' +#define ID_NUM 'N' +#define ID_STR 'S' +#define ID_FUN 'F' +#define SIGNATURE "Lua" +#define VERSION 0x31 /* last format change was in 3.1 */ +#define TEST_FLOAT 0.123456789e-23 /* a float for testing representation */ + +#define IsMain(f) (f->lineDefined==0) + +TProtoFunc* luaU_undump1(ZIO* Z); /* load one chunk */ + +#endif diff --git a/undump.c b/undump.c deleted file mode 100644 index 80f131de..00000000 --- a/undump.c +++ /dev/null @@ -1,318 +0,0 @@ -/* -** undump.c -** load bytecodes from files -*/ - -char* rcs_undump="$Id: undump.c,v 1.25 1997/07/29 19:44:02 roberto Exp roberto $"; - -#include -#include -#include "auxlib.h" -#include "opcode.h" -#include "luamem.h" -#include "table.h" -#include "undump.h" -#include "zio.h" - -static int swapword=0; -static int swapfloat=0; -static TFunc* Main=NULL; /* functions in a chunk */ -static TFunc* lastF=NULL; - -static void FixCode(Byte* code, Byte* end) /* swap words */ -{ - Byte* p; - for (p=code; p!=end;) - { - int op=*p; - switch (op) - { - case PUSHNIL: - case PUSH0: - case PUSH1: - case PUSH2: - case PUSHLOCAL0: - case PUSHLOCAL1: - case PUSHLOCAL2: - case PUSHLOCAL3: - case PUSHLOCAL4: - case PUSHLOCAL5: - case PUSHLOCAL6: - case PUSHLOCAL7: - case PUSHLOCAL8: - case PUSHLOCAL9: - case PUSHINDEXED: - case STORELOCAL0: - case STORELOCAL1: - case STORELOCAL2: - case STORELOCAL3: - case STORELOCAL4: - case STORELOCAL5: - case STORELOCAL6: - case STORELOCAL7: - case STORELOCAL8: - case STORELOCAL9: - case STOREINDEXED0: - case ADJUST0: - case EQOP: - case LTOP: - case LEOP: - case GTOP: - case GEOP: - case ADDOP: - case SUBOP: - case MULTOP: - case DIVOP: - case POWOP: - case CONCOP: - case MINUSOP: - case NOTOP: - case RETCODE0: - p++; - break; - case PUSHBYTE: - case PUSHLOCAL: - case STORELOCAL: - case STOREINDEXED: - case STORELIST0: - case ADJUST: - case RETCODE: - case VARARGS: - case STOREMAP: - p+=2; - break; - case STORELIST: - case CALLFUNC: - p+=3; - break; - case PUSHWORD: - case PUSHSELF: - case CREATEARRAY: - case ONTJMP: - case ONFJMP: - case JMP: - case UPJMP: - case IFFJMP: - case IFFUPJMP: - case SETLINE: - case PUSHGLOBAL: - case STOREGLOBAL: - { - Byte t; - t=p[1]; p[1]=p[2]; p[2]=t; - p+=3; - break; - } - case STORERECORD: - { - int n=*++p; - p++; - while (n--) - { - Byte t; - t=p[0]; p[0]=p[1]; p[1]=t; - p+=2; - } - break; - } - default: - luaL_verror("corrupt binary file: bad opcode %d at %d\n", - op,(int)(p-code)); - break; - } - } -} - -static void Unthread(Byte* code, int i, int v) -{ - while (i!=0) - { - Word w; - Byte* p=code+i; - memcpy(&w,p,sizeof(w)); - i=w; w=v; - memcpy(p,&w,sizeof(w)); - } -} - -static int LoadWord(ZIO* Z) -{ - Word w; - zread(Z,&w,sizeof(w)); - if (swapword) - { - Byte* p=(Byte*)&w; - Byte t; - t=p[0]; p[0]=p[1]; p[1]=t; - } - return w; -} - -static int LoadSize(ZIO* Z) -{ - Word hi=LoadWord(Z); - Word lo=LoadWord(Z); - int s=(hi<<16)|lo; - if ((Word)s != s) lua_error("code too long"); - return s; -} - -static void* LoadBlock(int size, ZIO* Z) -{ - void* b=luaI_malloc(size); - zread(Z,b,size); - return b; -} - -static char* LoadString(ZIO* Z) -{ - int size=LoadWord(Z); - char *b=luaI_buffer(size); - zread(Z,b,size); - return b; -} - -static char* LoadNewString(ZIO* Z) -{ - return LoadBlock(LoadWord(Z),Z); -} - -static void LoadFunction(ZIO* Z) -{ - int size; - TFunc* tf=new(TFunc); - tf->next=NULL; - tf->locvars=NULL; - size=LoadSize(Z); - tf->lineDefined=LoadWord(Z); - if (IsMain(tf)) /* new main */ - { - tf->fileName=LoadNewString(Z); - Main=lastF=tf; - } - else /* fix PUSHFUNCTION */ - { - tf->marked=LoadWord(Z); - tf->fileName=Main->fileName; - memcpy(Main->code+tf->marked,&tf,sizeof(tf)); - lastF=lastF->next=tf; - } - tf->code=LoadBlock(size,Z); - if (swapword || swapfloat) FixCode(tf->code,tf->code+size); - while (1) /* unthread */ - { - int c=zgetc(Z); - if (c==ID_VAR) /* global var */ - { - int i=LoadWord(Z); - char* s=LoadString(Z); - int v=luaI_findsymbolbyname(s); - Unthread(tf->code,i,v); - } - else if (c==ID_STR) /* constant string */ - { - int i=LoadWord(Z); - char* s=LoadString(Z); - int v; /*=luaI_findconstantbyname(s); ??????? */ - Unthread(tf->code,i,v); - } - else - { - zungetc(Z); - break; - } - } -} - -static void LoadSignature(ZIO* Z) -{ - char* s=SIGNATURE; - while (*s!=0 && zgetc(Z)==*s) - ++s; - if (*s!=0) lua_error("cannot load binary file: bad signature"); -} - -static void LoadHeader(ZIO* Z) -{ - Word w,tw=TEST_WORD; - float f,tf=TEST_FLOAT; - int version; - LoadSignature(Z); - version=zgetc(Z); - if (version>0x23) /* after 2.5 */ - { - int oldsizeofW=zgetc(Z); - int oldsizeofF=zgetc(Z); - int oldsizeofP=zgetc(Z); - if (oldsizeofW!=2) - luaL_verror( - "cannot load binary file created on machine with sizeof(Word)=%d; " - "expected 2",oldsizeofW); - if (oldsizeofF!=4) - luaL_verror( - "cannot load binary file created on machine with sizeof(float)=%d; " - "expected 4\nnot an IEEE machine?",oldsizeofF); - if (oldsizeofP!=sizeof(TFunc*)) /* TODO: pack? */ - luaL_verror( - "cannot load binary file created on machine with sizeof(TFunc*)=%d; " - "expected %d",oldsizeofP,(int)sizeof(TFunc*)); - } - zread(Z,&w,sizeof(w)); /* test word */ - if (w!=tw) - { - swapword=1; - } - zread(Z,&f,sizeof(f)); /* test float */ - if (f!=tf) - { - Byte* p=(Byte*)&f; - Byte t; - swapfloat=1; - t=p[0]; p[0]=p[3]; p[3]=t; - t=p[1]; p[1]=p[2]; p[2]=t; - if (f!=tf) /* TODO: try another perm? */ - lua_error("cannot load binary file: unknown float representation"); - } -} - -static void LoadChunk(ZIO* Z) -{ - LoadHeader(Z); - while (1) - { - int c=zgetc(Z); - if (c==ID_FUN) LoadFunction(Z); else { zungetc(Z); break; } - } -} - -/* -** load one chunk from a file. -** return list of functions found, headed by main, or NULL at EOF. -*/ -TFunc* luaI_undump1(ZIO* Z) -{ - int c=zgetc(Z); - if (c==ID_CHUNK) - { - LoadChunk(Z); - return Main; - } - else if (c!=EOZ) - lua_error("not a lua binary file"); - return NULL; -} - -/* -** load and run all chunks in a file -*/ -int luaI_undump(ZIO* Z) -{ - TFunc* m; - while ((m=luaI_undump1(Z))) - { - int status=luaI_dorun(m); -/* luaI_freefunc(m); ???*/ - if (status!=0) return status; - } - return 0; -} diff --git a/undump.h b/undump.h deleted file mode 100644 index 86da43af..00000000 --- a/undump.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -** undump.h -** definitions for lua decompiler -** $Id: undump.h,v 1.5 1997/06/16 16:50:22 roberto Exp roberto $ -*/ - -#ifndef undump_h -#define undump_h - -#include "func.h" -#include "zio.h" - -#define IsMain(f) (f->lineDefined==0) - -/* definitions for chunk headers */ - -#define ID_CHUNK 27 /* ESC */ -#define ID_FUN 'F' -#define ID_VAR 'V' -#define ID_STR 'S' -#define SIGNATURE "Lua" -#define VERSION 0x25 /* last format change was in 2.5 */ -#define TEST_WORD 0x1234 /* a word for testing byte ordering */ -#define TEST_FLOAT 0.123456789e-23 /* a float for testing representation */ - - -TFunc* luaI_undump1(ZIO* Z); -int luaI_undump(ZIO* Z); /* load all chunks */ - -#endif -- cgit v1.2.3-55-g6feb