| /* |
| ** 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 <stdio.h> |
| #include <string.h> |
| #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; |
| } |