lundump.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. ** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $
  3. ** load precompiled Lua chunks
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <string.h>
  7. #define lundump_c
  8. #define LUA_CORE
  9. #include "lua.h"
  10. #include "ldebug.h"
  11. #include "ldo.h"
  12. #include "lfunc.h"
  13. #include "lmem.h"
  14. #include "lobject.h"
  15. #include "lstring.h"
  16. #include "lundump.h"
  17. #include "lzio.h"
  18. typedef struct {
  19. lua_State* L;
  20. ZIO* Z;
  21. Mbuffer* b;
  22. const char* name;
  23. int swap;
  24. int numsize;
  25. int toflt;
  26. size_t total;
  27. } LoadState;
  28. #ifdef LUAC_TRUST_BINARIES
  29. #define IF(c,s)
  30. #define error(S,s)
  31. #else
  32. #define IF(c,s) if (c) error(S,s)
  33. static void error(LoadState* S, const char* why)
  34. {
  35. luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
  36. luaD_throw(S->L,LUA_ERRSYNTAX);
  37. }
  38. #endif
  39. #define LoadByte(S) (lu_byte)LoadChar(S)
  40. #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
  41. #define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
  42. static void LoadBlock(LoadState* S, void* b, size_t size)
  43. {
  44. size_t r=luaZ_read(S->Z,b,size);
  45. IF (r!=0, "unexpected end");
  46. S->total+=size;
  47. }
  48. static void LoadMem (LoadState* S, void* b, int n, size_t size)
  49. {
  50. LoadBlock(S,b,n*size);
  51. if (S->swap && b)
  52. {
  53. char* p=(char*) b;
  54. char c;
  55. switch (size)
  56. {
  57. case 1:
  58. break;
  59. case 2:
  60. while (n--)
  61. {
  62. c=p[0]; p[0]=p[1]; p[1]=c;
  63. p+=2;
  64. }
  65. break;
  66. case 4:
  67. while (n--)
  68. {
  69. c=p[0]; p[0]=p[3]; p[3]=c;
  70. c=p[1]; p[1]=p[2]; p[2]=c;
  71. p+=4;
  72. }
  73. break;
  74. case 8:
  75. while (n--)
  76. {
  77. c=p[0]; p[0]=p[7]; p[7]=c;
  78. c=p[1]; p[1]=p[6]; p[6]=c;
  79. c=p[2]; p[2]=p[5]; p[5]=c;
  80. c=p[3]; p[3]=p[4]; p[4]=c;
  81. p+=8;
  82. }
  83. break;
  84. default:
  85. IF(1, "bad size");
  86. break;
  87. }
  88. }
  89. }
  90. static int LoadChar(LoadState* S)
  91. {
  92. char x;
  93. LoadVar(S,x);
  94. return x;
  95. }
  96. static void Align4(LoadState* S)
  97. {
  98. while(S->total&3)
  99. LoadChar(S);
  100. }
  101. static int LoadInt(LoadState* S)
  102. {
  103. int x;
  104. LoadVar(S,x);
  105. IF (x<0, "bad integer");
  106. return x;
  107. }
  108. static lua_Number LoadNumber(LoadState* S)
  109. {
  110. lua_Number x;
  111. if(S->toflt)
  112. {
  113. switch(S->numsize)
  114. {
  115. case 1: {
  116. int8_t y;
  117. LoadVar(S,y);
  118. x = (lua_Number)y;
  119. } break;
  120. case 2: {
  121. int16_t y;
  122. LoadVar(S,y);
  123. x = (lua_Number)y;
  124. } break;
  125. case 4: {
  126. int32_t y;
  127. LoadVar(S,y);
  128. x = (lua_Number)y;
  129. } break;
  130. case 8: {
  131. int64_t y;
  132. LoadVar(S,y);
  133. x = (lua_Number)y;
  134. } break;
  135. default: lua_assert(0);
  136. }
  137. }
  138. else
  139. {
  140. LoadVar(S,x); /* should probably handle more cases for float here... */
  141. }
  142. return x;
  143. }
  144. static TString* LoadString(LoadState* S)
  145. {
  146. int32_t size;
  147. LoadVar(S,size);
  148. if (size==0)
  149. return NULL;
  150. else
  151. {
  152. char* s;
  153. if (!luaZ_direct_mode(S->Z)) {
  154. s = luaZ_openspace(S->L,S->b,size);
  155. LoadBlock(S,s,size);
  156. return luaS_newlstr(S->L,s,size-1); /* remove trailing zero */
  157. } else {
  158. s = (char*)luaZ_get_crt_address(S->Z);
  159. LoadBlock(S,NULL,size);
  160. return luaS_newrolstr(S->L,s,size-1);
  161. }
  162. }
  163. }
  164. static void LoadCode(LoadState* S, Proto* f)
  165. {
  166. int n=LoadInt(S);
  167. Align4(S);
  168. if (!luaZ_direct_mode(S->Z)) {
  169. f->code=luaM_newvector(S->L,n,Instruction);
  170. LoadVector(S,f->code,n,sizeof(Instruction));
  171. } else {
  172. f->code=(Instruction*)luaZ_get_crt_address(S->Z);
  173. LoadVector(S,NULL,n,sizeof(Instruction));
  174. }
  175. f->sizecode=n;
  176. }
  177. static Proto* LoadFunction(LoadState* S, TString* p);
  178. static void LoadConstants(LoadState* S, Proto* f)
  179. {
  180. int i,n;
  181. n=LoadInt(S);
  182. f->k=luaM_newvector(S->L,n,TValue);
  183. f->sizek=n;
  184. for (i=0; i<n; i++) setnilvalue(&f->k[i]);
  185. for (i=0; i<n; i++)
  186. {
  187. TValue* o=&f->k[i];
  188. int t=LoadChar(S);
  189. switch (t)
  190. {
  191. case LUA_TNIL:
  192. setnilvalue(o);
  193. break;
  194. case LUA_TBOOLEAN:
  195. setbvalue(o,LoadChar(S)!=0);
  196. break;
  197. case LUA_TNUMBER:
  198. setnvalue(o,LoadNumber(S));
  199. break;
  200. case LUA_TSTRING:
  201. setsvalue2n(S->L,o,LoadString(S));
  202. break;
  203. default:
  204. error(S,"bad constant");
  205. break;
  206. }
  207. }
  208. n=LoadInt(S);
  209. f->p=luaM_newvector(S->L,n,Proto*);
  210. f->sizep=n;
  211. for (i=0; i<n; i++) f->p[i]=NULL;
  212. for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
  213. }
  214. static void LoadDebug(LoadState* S, Proto* f)
  215. {
  216. int i,n;
  217. n=LoadInt(S);
  218. Align4(S);
  219. if (!luaZ_direct_mode(S->Z)) {
  220. f->lineinfo=luaM_newvector(S->L,n,int);
  221. LoadVector(S,f->lineinfo,n,sizeof(int));
  222. } else {
  223. f->lineinfo=(int*)luaZ_get_crt_address(S->Z);
  224. LoadVector(S,NULL,n,sizeof(int));
  225. }
  226. f->sizelineinfo=n;
  227. n=LoadInt(S);
  228. f->locvars=luaM_newvector(S->L,n,LocVar);
  229. f->sizelocvars=n;
  230. for (i=0; i<n; i++) f->locvars[i].varname=NULL;
  231. for (i=0; i<n; i++)
  232. {
  233. f->locvars[i].varname=LoadString(S);
  234. f->locvars[i].startpc=LoadInt(S);
  235. f->locvars[i].endpc=LoadInt(S);
  236. }
  237. n=LoadInt(S);
  238. f->upvalues=luaM_newvector(S->L,n,TString*);
  239. f->sizeupvalues=n;
  240. for (i=0; i<n; i++) f->upvalues[i]=NULL;
  241. for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
  242. }
  243. static Proto* LoadFunction(LoadState* S, TString* p)
  244. {
  245. Proto* f;
  246. if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
  247. f=luaF_newproto(S->L);
  248. if (luaZ_direct_mode(S->Z)) proto_readonly(f);
  249. setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
  250. f->source=LoadString(S); if (f->source==NULL) f->source=p;
  251. f->linedefined=LoadInt(S);
  252. f->lastlinedefined=LoadInt(S);
  253. f->nups=LoadByte(S);
  254. f->numparams=LoadByte(S);
  255. f->is_vararg=LoadByte(S);
  256. f->maxstacksize=LoadByte(S);
  257. LoadCode(S,f);
  258. LoadConstants(S,f);
  259. LoadDebug(S,f);
  260. IF (!luaG_checkcode(f), "bad code");
  261. S->L->top--;
  262. S->L->nCcalls--;
  263. return f;
  264. }
  265. static void LoadHeader(LoadState* S)
  266. {
  267. char h[LUAC_HEADERSIZE];
  268. char s[LUAC_HEADERSIZE];
  269. int intck = (((lua_Number)0.5)==0); /* 0=float, 1=int */
  270. luaU_header(h);
  271. LoadBlock(S,s,LUAC_HEADERSIZE);
  272. S->swap=(s[6]!=h[6]); s[6]=h[6]; /* Check if byte-swapping is needed */
  273. S->numsize=h[10]=s[10]; /* length of lua_Number */
  274. S->toflt=(s[11]>intck); /* check if conversion from int lua_Number to flt is needed */
  275. if(S->toflt) s[11]=h[11];
  276. IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
  277. }
  278. /*
  279. ** load precompiled chunk
  280. */
  281. Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
  282. {
  283. LoadState S;
  284. if (*name=='@' || *name=='=')
  285. S.name=name+1;
  286. else if (*name==LUA_SIGNATURE[0])
  287. S.name="binary string";
  288. else
  289. S.name=name;
  290. S.L=L;
  291. S.Z=Z;
  292. S.b=buff;
  293. LoadHeader(&S);
  294. S.total=0;
  295. return LoadFunction(&S,luaS_newliteral(L,"=?"));
  296. }
  297. /*
  298. * make header
  299. */
  300. void luaU_header (char* h)
  301. {
  302. int x=1;
  303. memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
  304. h+=sizeof(LUA_SIGNATURE)-1;
  305. *h++=(char)LUAC_VERSION;
  306. *h++=(char)LUAC_FORMAT;
  307. *h++=(char)*(char*)&x; /* endianness */
  308. *h++=(char)sizeof(int);
  309. *h++=(char)sizeof(int32_t);
  310. *h++=(char)sizeof(Instruction);
  311. *h++=(char)sizeof(lua_Number);
  312. *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
  313. }