luat_luf_undump.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. /*
  2. ** $Id: lundump.c,v 2.44.1.1 2017/04/19 17:20:42 roberto Exp $
  3. ** load precompiled Lua chunks
  4. ** See Copyright Notice in lua.h
  5. */
  6. #define lundump_c
  7. #define LUA_CORE
  8. #include "lprefix.h"
  9. #include <string.h>
  10. #include "lua.h"
  11. #include "ldebug.h"
  12. #include "ldo.h"
  13. #include "lfunc.h"
  14. #include "lmem.h"
  15. #include "lobject.h"
  16. #include "lstring.h"
  17. #include "lundump.h"
  18. #include "lzio.h"
  19. #include "ltable.h"
  20. #include "luat_base.h"
  21. #include "luat_fs.h"
  22. #define LUAT_LOG_TAG "undump"
  23. #include "luat_log.h"
  24. #define LUF_SIGNATURE "\x1cLUF"
  25. #if !defined(luai_verifycode)
  26. #define luai_verifycode(L,b,f) /* empty */
  27. #endif
  28. typedef struct {
  29. lua_State *L;
  30. ZIO *Z;
  31. const char *name;
  32. } LoadState;
  33. static void dumpHex(const char* tag, void* ptr, size_t len) {
  34. uint8_t* c = (uint8_t*)ptr;
  35. for (size_t i = 0; i < len / 8; i++)
  36. {
  37. LLOGD("%s %p %02X %02X %02X %02X %02X %02X %02X %02X", tag, &c[i*8], c[i*8], c[i*8+1], c[i*8+2], c[i*8+3],
  38. c[i*8+4], c[i*8+5], c[i*8+6], c[i*8+7]);
  39. }
  40. }
  41. static l_noret error(LoadState *S, const char *why) {
  42. luaO_pushfstring(S->L, "luf %s: %s precompiled chunk", S->name, why);
  43. luaD_throw(S->L, LUA_ERRSYNTAX);
  44. }
  45. /*
  46. ** All high-level loads go through LoadVector; you can change it to
  47. ** adapt to the endianness of the input
  48. */
  49. #define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0]))
  50. static void LoadBlock (LoadState *S, void *b, size_t size) {
  51. if (luaZ_read(S->Z, b, size) != 0)
  52. error(S, "truncated");
  53. }
  54. static void* DistBlock (LoadState *S, size_t size) {
  55. uint8_t b = 0;
  56. const char* p = S->Z->p;
  57. for (size_t i = 0; i < size; i++)
  58. {
  59. if (luaZ_read(S->Z, &b, 1) != 0)
  60. error(S, "truncated");
  61. }
  62. return (void*)p;
  63. }
  64. #define LoadVar(S,x) LoadVector(S,&x,1)
  65. static lu_byte LoadByte (LoadState *S) {
  66. lu_byte x;
  67. LoadVar(S, x);
  68. return x;
  69. }
  70. static int LoadInt (LoadState *S) {
  71. int x;
  72. LoadVar(S, x);
  73. return x;
  74. }
  75. static lua_Number LoadNumber (LoadState *S) {
  76. lua_Number x;
  77. LoadVar(S, x);
  78. return x;
  79. }
  80. static lua_Integer LoadInteger (LoadState *S) {
  81. lua_Integer x;
  82. LoadVar(S, x);
  83. return x;
  84. }
  85. // static TString *LoadString (LoadState *S, Proto *p) {
  86. // lu_byte t = LoadByte(S);
  87. // if (t == 0)
  88. // return NULL;
  89. // TString * ts = (TString*)S->Z->p;
  90. // // LLOGD("LoadString >> %d %p", tsslen(ts), ts);
  91. // DistBlock(S, sizeof(TString) + tsslen(ts) + 1);
  92. // // LLOGD("LoadString >> %s", getstr(ts));
  93. // return ts;
  94. // }
  95. static void LoadCode (LoadState *S, Proto *f) {
  96. // int n = LoadInt(S);
  97. // LLOGD("LoadCode %d %d", n, sizeof(Instruction) * n);
  98. // f->sizecode = n;
  99. // f->code = luat_heap_malloc(sizeof(Instruction) * f->sizecode);
  100. // memcpy(f->code, S->Z->p, sizeof(Instruction) * f->sizecode);
  101. f->code = DistBlock(S, sizeof(Instruction) * f->sizecode);
  102. //f->code = ((uint8_t*)f->code) + 2;
  103. LLOGD("f->code %p", f->code);
  104. for (size_t i = 0; i < f->sizecode; i++)
  105. {
  106. LLOGD("Code %02X -> %08X", i, f->code[i]);
  107. }
  108. }
  109. static void LoadFunction(LoadState *S, Proto *f, TString *psource);
  110. static void LoadConstants (LoadState *S, Proto *f) {
  111. // int i;
  112. // int n = LoadInt(S);
  113. // LLOGD("LoadConstants %d %d", n, sizeof(TValue) * n);
  114. // f->sizek = n;
  115. // 指向常数数组
  116. f->k = DistBlock(S, sizeof(TValue) * f->sizek);
  117. // 跳过字符串段
  118. for (size_t i = 0; i < f->sizek; i++)
  119. {
  120. TValue *t = &f->k[i];
  121. switch (ttype(t))
  122. {
  123. case LUA_TSHRSTR:
  124. case LUA_TLNGSTR:
  125. LLOGD("const string %p %s", tsvalue(t), getstr(tsvalue(t)));
  126. break;
  127. default:
  128. break;
  129. }
  130. }
  131. // LLOGD("1>>LoadConstants %02X %02X %02X %02X", *(S->Z->p), *(S->Z->p + 1), *(S->Z->p + 2), *(S->Z->p + 3));
  132. // n = LoadInt(S);
  133. // LLOGD("LoadConstants skip Strings %d", n);
  134. // DistBlock(S, sizeof(char) * n);
  135. // LLOGD("2>>LoadConstants %02X %02X %02X %02X", *(S->Z->p), *(S->Z->p + 1), *(S->Z->p + 2), *(S->Z->p + 3));
  136. }
  137. static void LoadProtos (LoadState *S, Proto *f) {
  138. int i;
  139. // int n = LoadInt(S);
  140. f->p = luaM_newvector(S->L, f->sizep, Proto *);
  141. // f->sizep = n;
  142. for (i = 0; i < f->sizep; i++)
  143. f->p[i] = NULL;
  144. for (i = 0; i < f->sizep; i++) {
  145. f->p[i] = luaF_newproto(S->L);
  146. luaC_objbarrier(S->L, f, f->p[i]);
  147. LoadFunction(S, f->p[i], f->source);
  148. }
  149. // LLOGD("LoadProtos %d %d", n, sizeof(Proto *) * n);
  150. }
  151. static void LoadUpvalues (LoadState *S, Proto *f) {
  152. int i, n;
  153. // n = LoadInt(S);
  154. // f->sizeupvalues = n;
  155. // LLOGD("LoadUpvalues %d %d", n, sizeof(Upvaldesc) * n);
  156. f->upvalues = DistBlock(S, sizeof(Upvaldesc) * f->sizeupvalues);
  157. // char* tmp = luaM_newvector(S->L, n, Upvaldesc);
  158. // memcpy(tmp, f->upvalues, sizeof(Upvaldesc) * n);
  159. // f->upvalues = tmp;
  160. // 跳过字符串段
  161. // n = LoadInt(S);
  162. // LLOGD("LoadUpvalues skip Strings %d", n);
  163. // DistBlock(S, sizeof(char) * n);
  164. }
  165. static void LoadDebug (LoadState *S, Proto *f) {
  166. int i, n;
  167. // n = LoadInt(S);
  168. // f->sizelineinfo = n;
  169. // LLOGD("LoadDebug sizelineinfo %d %d", n, sizeof(int) * n);
  170. f->lineinfo = DistBlock(S, sizeof(int) * f->sizelineinfo);
  171. // n = LoadInt(S);
  172. // f->sizelocvars = n;
  173. // LLOGD("LoadDebug sizelocvars %d %d", n, sizeof(LocVar) * n);
  174. f->locvars = DistBlock(S, sizeof(LocVar) * f->sizelocvars);
  175. // n = LoadInt(S);
  176. // DistBlock(S, sizeof(char) * n);
  177. }
  178. static void LoadFunction (LoadState *S, Proto *f, TString *psource) {
  179. //LLOGD(">> %02X %02X %02X %02X", *(S->Z->p), *(S->Z->p + 1), *(S->Z->p + 2), *(S->Z->p + 3));
  180. f->source = psource; /* reuse parent's source */
  181. if (f->source)
  182. LLOGI("%s %d source %s", __FILE__, __LINE__, getstr(f->source));
  183. else
  184. LLOGD("no source ?");
  185. f->linedefined = LoadInt(S);
  186. f->lastlinedefined = LoadInt(S);
  187. f->numparams = LoadByte(S);
  188. f->is_vararg = LoadByte(S);
  189. f->maxstacksize = LoadByte(S);
  190. LoadByte(S); // f->source != NULL ?
  191. // LLOGD("linedefined %d", f->linedefined);
  192. // LLOGD("lastlinedefined %d", f->lastlinedefined);
  193. // LLOGD("numparams %d", f->numparams);
  194. // LLOGD("is_vararg %d", f->is_vararg);
  195. // LLOGD("maxstacksize %d", f->maxstacksize);
  196. f->sizecode = LoadInt(S);
  197. f->sizek = LoadInt(S);
  198. f->sizeupvalues = LoadInt(S);
  199. f->sizep = LoadInt(S);
  200. f->sizelineinfo = LoadInt(S);
  201. f->sizelocvars = LoadInt(S);
  202. // LLOGD("sizecode %d", f->sizecode);
  203. // LLOGD("sizek %d", f->sizek);
  204. // LLOGD("sizeupvalues %d", f->sizeupvalues);
  205. // LLOGD("sizep %d", f->sizep);
  206. // LLOGD("sizelineinfo %d", f->sizelineinfo);
  207. // LLOGD("sizelocvars %d", f->sizelocvars);
  208. LoadCode(S, f);
  209. LoadConstants(S, f);
  210. LoadUpvalues(S, f);
  211. LoadProtos(S, f);
  212. LoadDebug(S, f);
  213. // for (size_t i = 0; i < f->sizelineinfo; i++)
  214. // {
  215. // LLOGD("lineinfo %d %p", f->lineinfo[i], &f->lineinfo[i]);
  216. // }
  217. // for (size_t i = 0; i < f->sizek; i++)
  218. // {
  219. // switch (f->k[i].tt_)
  220. // {
  221. // case LUA_TSHRSTR:
  222. // case LUA_TLNGSTR:
  223. // // LLOGD("const string %s", getstr(tsvalue(&f->k[i])));
  224. // LLOGD("const string %s", getstr(tsvalue(&f->k[i])));
  225. // break;
  226. // }
  227. // }
  228. // for (size_t i = 0; i < f->sizelocvars; i++)
  229. // {
  230. // LLOGD("locval string %s", getstr(f->locvars[i].varname));
  231. // }
  232. LLOGD("f->upvalues %p %08X", f->upvalues, (uint32_t)f->upvalues);
  233. for (size_t i = 0; i < f->sizeupvalues; i++)
  234. {
  235. // LLOGD("upval string %s", getstr(f->upvalues[i].name));
  236. LLOGD("upval string %p", f->upvalues[i].name);
  237. }
  238. }
  239. static void checkliteral (LoadState *S, const char *s, const char *msg) {
  240. char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
  241. size_t len = strlen(s);
  242. // buff[len] = 0;
  243. LoadVector(S, buff, len);
  244. // LLOGD("buff>> %02X %02X %02X %02X", buff[0], buff[1], buff[2], buff[3]);
  245. // LLOGD("s>> %02X %02X %02X %02X", s[0], s[1], s[2], s[3]);
  246. if (memcmp(s, buff, len) != 0)
  247. error(S, msg);
  248. }
  249. static void fchecksize (LoadState *S, size_t size, const char *tname) {
  250. if (LoadByte(S) != size)
  251. error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname));
  252. }
  253. #define checksize(S,t) fchecksize(S,sizeof(t),#t)
  254. static void checkHeader (LoadState *S) {
  255. checkliteral(S, LUF_SIGNATURE + 1, "not a"); /* 1st char already checked */
  256. if (LoadByte(S) != LUAC_VERSION)
  257. error(S, "version mismatch in");
  258. if (LoadByte(S) != 1)
  259. error(S, "format mismatch in");
  260. checkliteral(S, LUAC_DATA, "corrupted");
  261. checksize(S, int);
  262. checksize(S, size_t);
  263. checksize(S, Instruction);
  264. checksize(S, lua_Integer);
  265. checksize(S, lua_Number);
  266. if (LoadInteger(S) != LUAC_INT)
  267. error(S, "endianness mismatch in");
  268. if (LoadNumber(S) != LUAC_NUM)
  269. error(S, "float format mismatch in");
  270. }
  271. extern void luat_os_print_heapinfo(const char* tag);
  272. typedef struct LoadS {
  273. const char *s;
  274. size_t size;
  275. } LoadS;
  276. static const char *getS (lua_State *L, void *ud, size_t *size) {
  277. LoadS *ls = (LoadS *)ud;
  278. (void)L; /* not used */
  279. if (ls->size == 0) return NULL;
  280. *size = ls->size;
  281. ls->size = 0;
  282. return ls->s;
  283. }
  284. /*
  285. ** load precompiled chunk
  286. */
  287. LClosure *luat_luf_undump(lua_State *L, const char* ptr, size_t len, const char *name) {
  288. LoadState S;
  289. LClosure *cl;
  290. ZIO z;
  291. LoadS ls;
  292. ls.s = ptr;
  293. ls.size = len;
  294. luaZ_init(L, &z, getS, &ls);
  295. zgetc(&z);
  296. S.name = name;
  297. S.L = L;
  298. S.Z = &z;
  299. checkHeader(&S);
  300. cl = luaF_newLclosure(L, LoadByte(&S));
  301. setclLvalue(L, L->top, cl);
  302. luaD_inctop(L);
  303. cl->p = luaF_newproto(L);
  304. // LLOGD("sizeupvalues %d", cl->nupvalues);
  305. luaC_objbarrier(L, cl, cl->p); // add by wendal, refer: https://github.com/lua/lua/commit/f5eb809d3f1da13683cd02184042e67228206205
  306. size_t s = LoadInt(&S);
  307. LoadFunction(&S, cl->p, (TString*)s);
  308. lua_assert(cl->nupvalues == cl->p->sizeupvalues);
  309. luai_verifycode(L, buff, cl->p);
  310. luaF_initupvals(L, cl);
  311. //-----------------
  312. // from lua_load
  313. LClosure *f = cl;
  314. if (f->nupvalues >= 1) { /* does it have an upvalue? */
  315. /* get global table from registry */
  316. Table *reg = hvalue(&G(L)->l_registry);
  317. const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
  318. /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
  319. setobj(L, f->upvals[0]->v, gt);
  320. luaC_upvalbarrier(L, f->upvals[0]);
  321. }
  322. //-----------------
  323. //sizeof(LClosure) + sizeof(Proto) + sizeof(UpVal);
  324. return cl;
  325. }
  326. #ifndef LoadF
  327. typedef struct LoadF {
  328. int n; /* number of pre-read characters */
  329. FILE *f; /* file being read */
  330. char buff[BUFSIZ]; /* area for reading file */
  331. } LoadF;
  332. #endif
  333. LClosure *luat_luf_undump2(lua_State *L, ZIO *Z, const char *name) {
  334. LoadState S;
  335. LClosure *cl;
  336. S.name = name;
  337. S.L = L;
  338. S.Z = Z;
  339. #ifdef LUAT_USE_FS_VFS
  340. LLOGD("try mmap");
  341. char* ptr = (char*)luat_vfs_mmap(((LoadF*)Z->data)->f);
  342. if (ptr != NULL) {
  343. LLOGD("found mmap %p", ptr);
  344. ZIO z;
  345. LoadS ls;
  346. ls.s = ptr;
  347. ls.size = 64*1024;
  348. luaZ_init(L, &z, getS, &ls);
  349. zgetc(&z);
  350. S.Z = &z;
  351. // LLOGD(">> %02X %02X %02X %02X", S.Z->p[0], S.Z->p[1], S.Z->p[2], S.Z->p[3]);
  352. // LLOGD(">> %02X %02X %02X %02X", S.Z->p[4], S.Z->p[5], S.Z->p[6], S.Z->p[7]);
  353. // LLOGD(">> %02X %02X %02X %02X", S.Z->p[8], S.Z->p[9], S.Z->p[10], S.Z->p[11]);
  354. }
  355. #endif
  356. // LLOGD("LClosure %d Proto %d Upvaldesc %d LocVal %d",
  357. // sizeof(LClosure), sizeof(Proto), sizeof(Upvaldesc), sizeof(LocVar));
  358. checkHeader(&S);
  359. cl = luaF_newLclosure(L, LoadByte(&S));
  360. // 有几个对齐用的字节
  361. size_t fd_offset = (size_t)S.Z->p;
  362. if (fd_offset % 0x04 != 0) {
  363. LLOGD("skip %d 0x00", fd_offset % 0x04);
  364. for (size_t i = 0; i < (4 - (fd_offset % 0x04)); i++)
  365. {
  366. LoadByte(&S);
  367. }
  368. }
  369. //
  370. setclLvalue(L, L->top, cl);
  371. luaD_inctop(L);
  372. cl->p = luaF_newproto(L);
  373. luaC_objbarrier(L, cl, cl->p); // add by wendal, refer: https://github.com/lua/lua/commit/f5eb809d3f1da13683cd02184042e67228206205
  374. size_t s = LoadInt(&S);
  375. LoadFunction(&S, cl->p, (TString*)s);
  376. lua_assert(cl->nupvalues == cl->p->sizeupvalues);
  377. luai_verifycode(L, buff, cl->p);
  378. // dumpHex("& upvalues", &cl->p->upvalues[0], 8);
  379. // dumpHex("& upvalues[0].name", &cl->p->upvalues[0].name, 8);
  380. // dumpHex("> upvalues[0].name", cl->p->upvalues[0].name, 8);
  381. // LLOGD("> getstr(upvalues[0].name) %p", getstr(cl->p->upvalues[0].name));
  382. // LLOGD("> getstr(upvalues[0].name) %s", getstr(cl->p->upvalues[0].name));
  383. // dumpHex("head", (char*)0x080E0000, 8);
  384. //dumpHex("lineinfo", cl->p->lineinfo, 8);
  385. //LLOGD("lineinfo %d %d", cl->p->lineinfo[0], cl->p->lineinfo[1]);
  386. return cl;
  387. }