lundump.c 8.3 KB

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