diff options
Diffstat (limited to 'lundump.c')
| -rw-r--r-- | lundump.c | 254 |
1 files changed, 116 insertions, 138 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lundump.c,v 1.25 2000/08/24 14:19:39 roberto Exp roberto $ | 2 | ** $Id: lundump.c,v 1.29 2000/06/28 14:12:55 lhf Exp lhf $ |
| 3 | ** load bytecodes from files | 3 | ** load bytecodes from files |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -7,8 +7,6 @@ | |||
| 7 | #include <stdio.h> | 7 | #include <stdio.h> |
| 8 | #include <string.h> | 8 | #include <string.h> |
| 9 | 9 | ||
| 10 | #include "lua.h" | ||
| 11 | |||
| 12 | #include "lauxlib.h" | 10 | #include "lauxlib.h" |
| 13 | #include "lfunc.h" | 11 | #include "lfunc.h" |
| 14 | #include "lmem.h" | 12 | #include "lmem.h" |
| @@ -16,6 +14,7 @@ | |||
| 16 | #include "lstring.h" | 14 | #include "lstring.h" |
| 17 | #include "lundump.h" | 15 | #include "lundump.h" |
| 18 | 16 | ||
| 17 | #define LoadVector(L,b,n,s,Z) LoadBlock(L,b,(n)*(s),Z) | ||
| 19 | #define LoadBlock(L,b,size,Z) ezread(L,Z,b,size) | 18 | #define LoadBlock(L,b,size,Z) ezread(L,Z,b,size) |
| 20 | #define LoadByte ezgetc | 19 | #define LoadByte ezgetc |
| 21 | 20 | ||
| @@ -43,41 +42,46 @@ static void ezread (lua_State* L, ZIO* Z, void* b, int n) | |||
| 43 | if (r!=0) unexpectedEOZ(L,Z); | 42 | if (r!=0) unexpectedEOZ(L,Z); |
| 44 | } | 43 | } |
| 45 | 44 | ||
| 46 | static unsigned int LoadWord (lua_State* L, ZIO* Z) | 45 | static void LoadReverse (lua_State* L, void* b, size_t size, ZIO* Z) |
| 47 | { | 46 | { |
| 48 | unsigned int hi=ezgetc(L,Z); | 47 | unsigned char *p=(unsigned char *) b+size; |
| 49 | unsigned int lo=ezgetc(L,Z); | 48 | int n=size; |
| 50 | return (hi<<8)|lo; | 49 | while (n--) *p--=ezgetc(L,Z); |
| 51 | } | 50 | } |
| 52 | 51 | ||
| 53 | static unsigned long LoadLong (lua_State* L, ZIO* Z) | 52 | static int LoadInt (lua_State* L, ZIO* Z, int swap) |
| 54 | { | 53 | { |
| 55 | unsigned long hi=LoadWord(L,Z); | 54 | int x; |
| 56 | unsigned long lo=LoadWord(L,Z); | 55 | if (swap) |
| 57 | return (hi<<16)|lo; | 56 | LoadReverse(L,&x,sizeof(x),Z); |
| 57 | else | ||
| 58 | LoadBlock(L,&x,sizeof(x),Z); | ||
| 59 | return x; | ||
| 58 | } | 60 | } |
| 59 | 61 | ||
| 60 | static Number LoadNumber (lua_State* L, ZIO* Z) | 62 | static size_t LoadSize (lua_State* L, ZIO* Z, int swap) |
| 61 | { | 63 | { |
| 62 | char b[256]; | 64 | size_t x; |
| 63 | int size=ezgetc(L,Z); | 65 | if (swap) |
| 64 | LoadBlock(L,b,size,Z); | 66 | LoadReverse(L,&x,sizeof(x),Z); |
| 65 | b[size]=0; | 67 | else |
| 66 | return luaU_str2d(L,b,ZNAME(Z)); | 68 | LoadBlock(L,&x,sizeof(x),Z); |
| 69 | return x; | ||
| 67 | } | 70 | } |
| 68 | 71 | ||
| 69 | static int LoadInt (lua_State* L, ZIO* Z, const char* message) | 72 | static Number LoadNumber (lua_State* L, ZIO* Z, int swap) |
| 70 | { | 73 | { |
| 71 | unsigned long l=LoadLong(L,Z); | 74 | Number x; |
| 72 | unsigned int i=l; | 75 | if (swap) |
| 73 | if (i!=l) luaL_verror(L,"%s in `%.255s';\n" | 76 | LoadReverse(L,&x,sizeof(x),Z); |
| 74 | " read %lu; expected %u",message,ZNAME(Z),l,-1); | 77 | else |
| 75 | return i; | 78 | LoadBlock(L,&x,sizeof(x),Z); |
| 79 | return x; | ||
| 76 | } | 80 | } |
| 77 | 81 | ||
| 78 | static TString* LoadString (lua_State* L, ZIO* Z) | 82 | static TString* LoadString (lua_State* L, ZIO* Z, int swap) |
| 79 | { | 83 | { |
| 80 | long size=LoadLong(L,Z); | 84 | size_t size=LoadSize(L,Z,swap); |
| 81 | if (size==0) | 85 | if (size==0) |
| 82 | return NULL; | 86 | return NULL; |
| 83 | else | 87 | else |
| @@ -88,96 +92,73 @@ static TString* LoadString (lua_State* L, ZIO* Z) | |||
| 88 | } | 92 | } |
| 89 | } | 93 | } |
| 90 | 94 | ||
| 91 | static void SwapCode (lua_State* L, Instruction* code, int size, ZIO* Z) | 95 | static void LoadCode (lua_State* L, Proto* tf, ZIO* Z, int swap) |
| 92 | { | 96 | { |
| 93 | unsigned char* p; | 97 | int size=LoadInt(L,Z,swap); |
| 94 | unsigned char c; | 98 | tf->code=luaM_newvector(L,size,Instruction); |
| 95 | if (sizeof(Instruction)==4) | 99 | LoadVector(L,tf->code,size,sizeof(*tf->code),Z); |
| 96 | while (size--) | 100 | #if 0 |
| 97 | { | 101 | if (swap) SwapBytes(tf->code,sizeof(*tf->code),size); |
| 98 | p=(unsigned char *) code++; | 102 | #endif |
| 99 | c=p[0]; p[0]=p[3]; p[3]=c; | 103 | if (tf->code[size-1]!=OP_END) luaL_verror(L,"bad code in `%.255s'",ZNAME(Z)); |
| 100 | c=p[1]; p[1]=p[2]; p[2]=c; | ||
| 101 | } | ||
| 102 | else if (sizeof(Instruction)==2) | ||
| 103 | while (size--) | ||
| 104 | { | ||
| 105 | p=(unsigned char *) code++; | ||
| 106 | c=p[0]; p[0]=p[1]; p[1]=c; | ||
| 107 | } | ||
| 108 | else | ||
| 109 | luaL_verror(L,"cannot swap code with %d-byte instructions in `%.255s'", | ||
| 110 | (int)sizeof(Instruction),ZNAME(Z)); | ||
| 111 | } | 104 | } |
| 112 | 105 | ||
| 113 | static void LoadCode (lua_State* L, Proto* tf, ZIO* Z) | 106 | static void LoadLocals (lua_State* L, Proto* tf, ZIO* Z, int swap) |
| 114 | { | 107 | { |
| 115 | int size=LoadInt(L,Z,"code too long"); | 108 | int i,n; |
| 116 | Instruction t=0,tt=TEST_CODE; | 109 | tf->nlocvars=n=LoadInt(L,Z,swap); |
| 117 | tf->code=luaM_newvector(L,size,Instruction); | 110 | tf->locvars=luaM_newvector(L,n,LocVar); |
| 118 | LoadBlock(L,tf->code,size*sizeof(*tf->code),Z); | 111 | for (i=0; i<n; i++) |
| 119 | if (tf->code[size-1]!=OP_END) luaL_verror(L,"bad code in `%.255s'",ZNAME(Z)); | ||
| 120 | LoadBlock(L,&t,sizeof(t),Z); | ||
| 121 | if (t!=tt) | ||
| 122 | { | 112 | { |
| 123 | Instruction ot=t; | 113 | tf->locvars[i].varname=LoadString(L,Z,swap); |
| 124 | SwapCode(L,&t,1,Z); | 114 | tf->locvars[i].startpc=LoadInt(L,Z,swap); |
| 125 | if (t!=tt) luaL_verror(L,"cannot swap code in `%.255s';\n" | 115 | tf->locvars[i].endpc=LoadInt(L,Z,swap); |
| 126 | " read 0x%08X; swapped to 0x%08X; expected 0x%08X", | ||
| 127 | ZNAME(Z),(unsigned long)ot,(unsigned long)t,(unsigned long)tt); | ||
| 128 | SwapCode(L,tf->code,size,Z); | ||
| 129 | } | 116 | } |
| 130 | } | 117 | } |
| 131 | 118 | ||
| 132 | static void LoadLocals (lua_State* L, Proto* tf, ZIO* Z) | 119 | static void LoadLines (lua_State* L, Proto* tf, ZIO* Z, int swap) |
| 133 | { | 120 | { |
| 121 | int n=LoadInt(L,Z,swap); | ||
| 122 | if (n==0) return; | ||
| 123 | tf->lineinfo=luaM_newvector(L,n,int); | ||
| 124 | LoadVector(L,tf->lineinfo,n,sizeof(*tf->lineinfo),Z); | ||
| 125 | #if 0 | ||
| 126 | if (swap) SwapBytes(tf->lineinfo,sizeof(*tf->lineinfo),n); | ||
| 127 | #endif | ||
| 134 | } | 128 | } |
| 135 | 129 | ||
| 136 | static Proto* LoadFunction (lua_State* L, ZIO* Z, int native); | 130 | static Proto* LoadFunction (lua_State* L, ZIO* Z, int swap); |
| 137 | 131 | ||
| 138 | static void LoadConstants (lua_State* L, Proto* tf, ZIO* Z, int native) | 132 | static void LoadConstants (lua_State* L, Proto* tf, ZIO* Z, int swap) |
| 139 | { | 133 | { |
| 140 | int i,n; | 134 | int i,n; |
| 141 | tf->nkstr=n=LoadInt(L,Z,"too many strings"); | 135 | tf->nkstr=n=LoadInt(L,Z,swap); |
| 142 | if (n>0) | 136 | tf->kstr=luaM_newvector(L,n,TString*); |
| 143 | { | 137 | for (i=0; i<n; i++) |
| 144 | tf->kstr=luaM_newvector(L,n,TString*); | 138 | tf->kstr[i]=LoadString(L,Z,swap); |
| 145 | for (i=0; i<n; i++) | 139 | tf->nknum=n=LoadInt(L,Z,swap); |
| 146 | { | 140 | tf->knum=luaM_newvector(L,n,Number); |
| 147 | TString* s=LoadString(L,Z); | 141 | LoadVector(L,tf->knum,n,sizeof(*tf->knum),Z); |
| 148 | LoadByte(L,Z); | 142 | if (swap) |
| 149 | tf->kstr[i]=s; | 143 | for (i=0; i<n; i++) tf->knum[i]=LoadNumber(L,Z,swap); /* TODO */ |
| 150 | } | 144 | tf->nkproto=n=LoadInt(L,Z,swap); |
| 151 | } | 145 | tf->kproto=luaM_newvector(L,n,Proto*); |
| 152 | tf->nknum=n=LoadInt(L,Z,"too many numbers"); | 146 | for (i=0; i<n; i++) |
| 153 | if (n>0) | 147 | tf->kproto[i]=LoadFunction(L,Z,swap); |
| 154 | { | 148 | } |
| 155 | tf->knum=luaM_newvector(L,n,Number); | 149 | |
| 156 | if (native) | 150 | static Proto* LoadFunction (lua_State* L, ZIO* Z, int swap) |
| 157 | LoadBlock(L,tf->knum,n*sizeof(*tf->knum),Z); | ||
| 158 | else | ||
| 159 | for (i=0; i<n; i++) tf->knum[i]=LoadNumber(L,Z); | ||
| 160 | } | ||
| 161 | tf->nkproto=n=LoadInt(L,Z,"too many functions"); | ||
| 162 | if (n>0) | ||
| 163 | { | ||
| 164 | tf->kproto=luaM_newvector(L,n,Proto*); | ||
| 165 | for (i=0; i<n; i++) tf->kproto[i]=LoadFunction(L,Z,native); | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | static Proto* LoadFunction (lua_State* L, ZIO* Z, int native) | ||
| 170 | { | 151 | { |
| 171 | Proto* tf=luaF_newproto(L); | 152 | Proto* tf=luaF_newproto(L); |
| 172 | tf->source=LoadString(L,Z); | 153 | tf->source=LoadString(L,Z,swap); |
| 173 | if (tf->source==NULL) tf->source=luaS_new(L,zname(Z)); | 154 | tf->lineDefined=LoadInt(L,Z,swap); |
| 174 | tf->lineDefined=LoadInt(L,Z,"lineDefined too large"); | 155 | tf->numparams=LoadInt(L,Z,swap); |
| 175 | tf->numparams=LoadInt(L,Z,"too many parameters"); | ||
| 176 | tf->is_vararg=LoadByte(L,Z); | 156 | tf->is_vararg=LoadByte(L,Z); |
| 177 | tf->maxstacksize=LoadInt(L,Z,"too much stack needed"); | 157 | tf->maxstacksize=LoadInt(L,Z,swap); |
| 178 | LoadCode(L,tf,Z); | 158 | LoadCode(L,tf,Z,swap); |
| 179 | LoadLocals(L,tf,Z); | 159 | LoadLocals(L,tf,Z,swap); |
| 180 | LoadConstants(L,tf,Z,native); | 160 | LoadLines(L,tf,Z,swap); |
| 161 | LoadConstants(L,tf,Z,swap); | ||
| 181 | return tf; | 162 | return tf; |
| 182 | } | 163 | } |
| 183 | 164 | ||
| @@ -189,11 +170,21 @@ static void LoadSignature (lua_State* L, ZIO* Z) | |||
| 189 | if (*s!=0) luaL_verror(L,"bad signature in `%.255s'",ZNAME(Z)); | 170 | if (*s!=0) luaL_verror(L,"bad signature in `%.255s'",ZNAME(Z)); |
| 190 | } | 171 | } |
| 191 | 172 | ||
| 173 | static void TestSize (lua_State* L, int s, const char* what, ZIO* Z) | ||
| 174 | { | ||
| 175 | int r=ezgetc(L,Z); | ||
| 176 | if (r!=s) | ||
| 177 | luaL_verror(L,"virtual machine mismatch in `%.255s':\n" | ||
| 178 | " %s is %d but read %d",ZNAME(Z),what,r,s); | ||
| 179 | } | ||
| 180 | |||
| 181 | #define TESTSIZE(s) TestSize(L,s,#s,Z) | ||
| 192 | #define V(v) v/16,v%16 | 182 | #define V(v) v/16,v%16 |
| 193 | 183 | ||
| 194 | static int LoadHeader (lua_State* L, ZIO* Z) | 184 | static int LoadHeader (lua_State* L, ZIO* Z) |
| 195 | { | 185 | { |
| 196 | int version,sizeofR,native; | 186 | int version,swap; |
| 187 | Number f=0,tf=TEST_NUMBER; | ||
| 197 | LoadSignature(L,Z); | 188 | LoadSignature(L,Z); |
| 198 | version=ezgetc(L,Z); | 189 | version=ezgetc(L,Z); |
| 199 | if (version>VERSION) | 190 | if (version>VERSION) |
| @@ -204,36 +195,20 @@ static int LoadHeader (lua_State* L, ZIO* Z) | |||
| 204 | luaL_verror(L,"`%.255s' too old:\n" | 195 | luaL_verror(L,"`%.255s' too old:\n" |
| 205 | " read version %d.%d; expected at least %d.%d", | 196 | " read version %d.%d; expected at least %d.%d", |
| 206 | ZNAME(Z),V(version),V(VERSION)); | 197 | ZNAME(Z),V(version),V(VERSION)); |
| 207 | { | 198 | swap=(luaU_endianess()!=ezgetc(L,Z)); /* need to swap bytes? */ |
| 208 | int I=ezgetc(L,Z); | 199 | TESTSIZE(sizeof(int)); |
| 209 | int i=ezgetc(L,Z); | 200 | TESTSIZE(sizeof(size_t)); |
| 210 | int op=ezgetc(L,Z); | 201 | TESTSIZE(sizeof(Instruction)); |
| 211 | int b=ezgetc(L,Z); | 202 | TESTSIZE(SIZE_INSTRUCTION); |
| 212 | if (I!=sizeof(Instruction) || i!=SIZE_INSTRUCTION || op!=SIZE_OP || b!=SIZE_B) | 203 | TESTSIZE(SIZE_OP); |
| 213 | luaL_verror(L,"virtual machine mismatch in `%.255s':\n" | 204 | TESTSIZE(SIZE_B); |
| 214 | " read %d-bit,%d-byte instructions, %d-bit opcodes, %d-bit b-arguments;\n" | 205 | TESTSIZE(sizeof(Number)); |
| 215 | " expected %d-bit,%d-byte instructions, %d-bit opcodes, %d-bit b-arguments", | 206 | f=LoadNumber(L,Z,swap); |
| 216 | ZNAME(Z),i,I,op,b,SIZE_INSTRUCTION,(int)sizeof(Instruction),SIZE_OP,SIZE_B); | 207 | if ((long)f!=(long)tf) /* disregard errors in last bit of fraction */ |
| 217 | } | 208 | luaL_verror(L,"unknown number format in `%.255s':\n" |
| 218 | sizeofR=ezgetc(L,Z); | 209 | " read " NUMBER_FMT "; expected " NUMBER_FMT, |
| 219 | native=(sizeofR!=0); | 210 | ZNAME(Z),f,tf); |
| 220 | if (native) /* test number representation */ | 211 | return swap; |
| 221 | { | ||
| 222 | if (sizeofR!=sizeof(Number)) | ||
| 223 | luaL_verror(L,"native number size mismatch in `%.255s':\n" | ||
| 224 | " read %d; expected %d", | ||
| 225 | ZNAME(Z),sizeofR,(int)sizeof(Number)); | ||
| 226 | else | ||
| 227 | { | ||
| 228 | Number f=0,tf=TEST_NUMBER; | ||
| 229 | LoadBlock(L,&f,sizeof(f),Z); | ||
| 230 | if ((long)f!=(long)tf) /* disregard errors in last bit of fraction */ | ||
| 231 | luaL_verror(L,"unknown number format in `%.255s':\n" | ||
| 232 | " read " NUMBER_FMT "; expected " NUMBER_FMT, | ||
| 233 | ZNAME(Z),f,tf); | ||
| 234 | } | ||
| 235 | } | ||
| 236 | return native; | ||
| 237 | } | 212 | } |
| 238 | 213 | ||
| 239 | static Proto* LoadChunk (lua_State* L, ZIO* Z) | 214 | static Proto* LoadChunk (lua_State* L, ZIO* Z) |
| @@ -245,23 +220,26 @@ static Proto* LoadChunk (lua_State* L, ZIO* Z) | |||
| 245 | ** load one chunk from a file or buffer | 220 | ** load one chunk from a file or buffer |
| 246 | ** return main if ok and NULL at EOF | 221 | ** return main if ok and NULL at EOF |
| 247 | */ | 222 | */ |
| 248 | Proto* luaU_undump1 (lua_State* L, ZIO* Z) | 223 | Proto* luaU_undump (lua_State* L, ZIO* Z) |
| 249 | { | 224 | { |
| 250 | int c=zgetc(Z); | 225 | int c=zgetc(Z); |
| 251 | if (c==ID_CHUNK) | 226 | if (c==ID_CHUNK) |
| 252 | return LoadChunk(L,Z); | 227 | return LoadChunk(L,Z); |
| 253 | else if (c!=EOZ) | 228 | else if (c!=EOZ) |
| 254 | luaL_verror(L,"`%.255s' is not a Lua binary file",ZNAME(Z)); | 229 | luaL_verror(L,"`%.255s' is not a precompiled Lua chunk",ZNAME(Z)); |
| 255 | return NULL; | 230 | return NULL; |
| 256 | } | 231 | } |
| 257 | 232 | ||
| 233 | Proto* luaU_undump1 (lua_State* L, ZIO* Z) | ||
| 234 | { | ||
| 235 | return luaU_undump(L,Z); | ||
| 236 | } | ||
| 237 | |||
| 258 | /* | 238 | /* |
| 259 | * convert number from text | 239 | ** find byte order |
| 260 | */ | 240 | */ |
| 261 | double luaU_str2d (lua_State* L, const char* b, const char* where) | 241 | int luaU_endianess (void) |
| 262 | { | 242 | { |
| 263 | double x; | 243 | int x=1; |
| 264 | if (!luaO_str2d(b,&x)) | 244 | return *(char*)&x; |
| 265 | luaL_verror(L,"cannot convert number `%.255s' in `%.255s'",b,where); | ||
| 266 | return x; | ||
| 267 | } | 245 | } |
