luat_luf_dump.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. /*
  2. ** $Id: ldump.c,v 2.37.1.1 2017/04/19 17:20:42 roberto Exp $
  3. ** save precompiled Lua chunks
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include "luat_base.h"
  7. #include "luat_malloc.h"
  8. #define ldump_c
  9. #define LUA_CORE
  10. #include "lprefix.h"
  11. #include <stddef.h>
  12. #include "lua.h"
  13. #include "lobject.h"
  14. #include "lstate.h"
  15. #include "lundump.h"
  16. #include "lstring.h"
  17. #include "lgc.h"
  18. #define LUAT_LOG_TAG "dump"
  19. #include "luat_log.h"
  20. #define white2gray(x) resetbits(x->marked, WHITEBITS)
  21. #define black2gray(x) resetbit(x->marked, BLACKBIT)
  22. // #define fslen(s) (sizeof(TString) + tsslen(s) + 1)
  23. static size_t fslen(TString *ts) {
  24. size_t t = sizeof(TString) + tsslen(ts) + 1;
  25. if (t % 0x04 != 0) {
  26. t += (4 - (t % 0x04));
  27. }
  28. return t;
  29. }
  30. #define LUF_SIGNATURE "\x1cLUF"
  31. typedef struct {
  32. lua_State *L;
  33. lua_Writer writer;
  34. void *data;
  35. int strip;
  36. int status;
  37. } DumpState;
  38. static void DumpString (const TString *s, DumpState *D);
  39. static size_t fd_offset = 0;
  40. static size_t str_offset = 0;
  41. typedef struct strpool
  42. {
  43. TString* ts[256];
  44. void* ptr[256];
  45. void* next;
  46. }strpool_t;
  47. static strpool_t *spool = NULL;
  48. static void spool_init(void) {
  49. spool = luat_heap_malloc(sizeof(strpool_t));
  50. memset(spool, 0, sizeof(strpool_t));
  51. }
  52. static void spool_deinit(void) {
  53. strpool_t *tmp = spool;
  54. while (tmp != NULL) {
  55. luat_heap_free(tmp);
  56. tmp = (strpool_t *)tmp->next;
  57. }
  58. }
  59. static void spool_dump(DumpState *D) {
  60. strpool_t *tmp = spool;
  61. while (tmp != NULL) {
  62. for (size_t i = 0; i < 256; i++)
  63. {
  64. if (tmp->ts[i] == NULL)
  65. return;
  66. DumpString(tmp->ts[i], D);
  67. }
  68. tmp = (strpool_t *)tmp->next;
  69. }
  70. }
  71. static TString* spool_add(TString* ts) {
  72. if (ts == NULL)
  73. return ts;
  74. strpool_t *tmp = spool;
  75. // strpool_t *next = NULL;
  76. while (tmp != NULL) {
  77. for (size_t i = 0; i < 256; i++)
  78. {
  79. if (tmp->ts[i] == NULL) {
  80. //LLOGD("add string [%s]", getstr(ts));
  81. tmp->ts[i] = ts;
  82. tmp->ptr[i] = (void*)(str_offset);
  83. str_offset += fslen(ts);
  84. LLOGD("spool_add new %s %p", getstr(ts), tmp->ptr[i]);
  85. return tmp->ptr[i];
  86. }
  87. if (!strcmp(getstr(ts), getstr(tmp->ts[i]))) {
  88. LLOGD("spool_add match %s %p", getstr(ts), tmp->ptr[i]);
  89. return tmp->ptr[i];
  90. }
  91. }
  92. if (tmp->next == NULL)
  93. break;
  94. tmp = tmp->next;
  95. }
  96. tmp->next = luat_heap_malloc(sizeof(strpool_t));
  97. memset(tmp->next, 0, sizeof(strpool_t));
  98. tmp->ts[0] = ts;
  99. tmp->ptr[0] = (void*)(str_offset);
  100. str_offset += fslen(ts);
  101. LLOGD("spool_add new %s %p", getstr(ts), tmp->ptr[0]);
  102. return tmp->ptr[0];
  103. }
  104. size_t countProtoDumpSize(Proto *f) {
  105. if (f == NULL)
  106. return 0;
  107. size_t count = 0;
  108. /*
  109. DumpInt(f->linedefined, D);
  110. DumpInt(f->lastlinedefined, D);
  111. DumpByte(f->numparams, D);
  112. DumpByte(f->is_vararg, D);
  113. DumpByte(f->maxstacksize, D);
  114. DumpByte(f->source == NULL ? 0 : 1, D);
  115. */
  116. count += sizeof(int) * 2 + sizeof(lu_byte) * 4;
  117. count += f->sizecode * sizeof(Instruction);
  118. count += f->sizek * sizeof(TValue);
  119. count += f->sizeupvalues * sizeof(Upvaldesc);
  120. count += f->sizelineinfo * sizeof(int);
  121. count += f->sizelocvars * sizeof(LocVar);
  122. for (size_t i = 0; i < f->sizep; i++)
  123. {
  124. count += countProtoDumpSize(f->p[i]);
  125. }
  126. count += sizeof(int) * 6; // sizeX * 6
  127. return count;
  128. }
  129. /*
  130. ** All high-level dumps go through DumpVector; you can change it to
  131. ** change the endianness of the result
  132. */
  133. #define DumpVector(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D)
  134. #define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D)
  135. // static TString* AddMockString(TString* ts) {
  136. // if (ts == NULL)
  137. // return ts;
  138. // TString* t = (TString*) (fd_offset + str_offset);
  139. // str_offset += (sizeof(TString) + tsslen(ts) + 1);
  140. // return t;
  141. // }
  142. static void DumpBlock (const void *b, size_t size, DumpState *D) {
  143. if (D->status == 0 && size > 0) {
  144. lua_unlock(D->L);
  145. D->status = (*D->writer)(D->L, b, size, D->data);
  146. lua_lock(D->L);
  147. }
  148. fd_offset += size;
  149. }
  150. #define DumpVar(x,D) DumpVector(&x,1,D);
  151. static void DumpByte (int y, DumpState *D) {
  152. lu_byte x = (lu_byte)y;
  153. DumpVar(x, D);
  154. }
  155. static void DumpInt (int x, DumpState *D) {
  156. DumpVar(x, D);
  157. }
  158. static void DumpNumber (lua_Number x, DumpState *D) {
  159. DumpVar(x, D);
  160. }
  161. static void DumpInteger (lua_Integer x, DumpState *D) {
  162. DumpVar(x, D);
  163. }
  164. static void DumpString (const TString *s, DumpState *D) {
  165. // size_t size = 0;
  166. // if (s == NULL) {
  167. // DumpByte(0, D);
  168. // return;
  169. // }
  170. // DumpByte(1, D);
  171. TString ts;
  172. memcpy(&ts, s, sizeof(TString));
  173. ts.next = NULL;
  174. if (ts.tt == LUA_TSHRSTR) {
  175. ts.u.hnext = NULL;
  176. // ts.u.lnglen = ts.shrlen;
  177. // ts.hash = (getstr(s), ts.shrlen, 0);
  178. ts.extra = 1;
  179. // ts.tt = LUA_TLNGSTR;
  180. }
  181. white2gray((&ts));
  182. //LLOGD("B>DumpString %d %d", fslen(s), fd_offset);
  183. DumpBlock(&ts, sizeof(TString), D);
  184. DumpBlock(getstr(s), tsslen(s)+1, D);
  185. if ((tsslen(s) + 1) % 0x04 != 0) {
  186. for (size_t i = 0; i < (4-((tsslen(s) + 1) % 0x04)); i++)
  187. {
  188. DumpByte(0, D);
  189. }
  190. }
  191. //LLOGD("A>DumpString %d %d", fslen(s), fd_offset);
  192. }
  193. static void DumpCode (const Proto *f, DumpState *D) {
  194. //DumpInt(f->sizecode, D);
  195. DumpVector(f->code, f->sizecode, D);
  196. for (size_t i = 0; i < f->sizecode; i++)
  197. {
  198. LLOGD("Code %02X -> %08X", i, f->code[i]);
  199. }
  200. }
  201. static void DumpFunction(const Proto *f, TString *psource, DumpState *D);
  202. static void DumpConstants (const Proto *f, DumpState *D) {
  203. int i;
  204. int n = f->sizek;
  205. //LLOGD("DumpConstants %d %d", n, n * sizeof(TValue));
  206. //DumpInt(n, D);
  207. //size_t init_offset = fd_offset + sizeof(TValue) * n + sizeof(int);
  208. //size_t i_offset = init_offset;
  209. TValue tmp;
  210. TString* ts;
  211. for (i = 0; i < n; i++) {
  212. const TValue *o = &f->k[i];
  213. switch (ttype(o)) {
  214. case LUA_TSHRSTR:
  215. case LUA_TLNGSTR:
  216. // {
  217. //memcpy(&tmp, o, sizeof(TValue));
  218. ts = spool_add(tsvalue(o));
  219. tmp.value_.gc = ts;
  220. tmp.tt_ = ttype(o);
  221. // tmp.tt_ = LUA_TLNGSTR;
  222. DumpBlock(&tmp, sizeof(TValue), D);
  223. break;
  224. // o = &tmp;
  225. // init_offset += fslen(tsvalue(o)) + 1;
  226. // //break;
  227. // }
  228. default:
  229. DumpBlock(o, sizeof(TValue), D);
  230. break;
  231. }
  232. }
  233. //LLOGD("DumpConstants1 Strings len %d %d %d %d", init_offset, i_offset, fd_offset, init_offset - i_offset);
  234. // DumpInt(init_offset - i_offset, D);
  235. // for (i = 0; i < n; i++) {
  236. // const TValue *o = &f->k[i];
  237. // switch (ttype(o)) {
  238. // case LUA_TSHRSTR:
  239. // case LUA_TLNGSTR:
  240. // {
  241. // DumpString(tsvalue(o), D);
  242. // break;
  243. // }
  244. // }
  245. // }
  246. //LLOGD("DumpConstants2 Strings len %d %d %d %d", init_offset, i_offset, fd_offset, init_offset - i_offset);
  247. }
  248. static void DumpProtos (const Proto *f, DumpState *D) {
  249. int i;
  250. int n = f->sizep;
  251. // DumpInt(n, D);
  252. for (i = 0; i < n; i++)
  253. DumpFunction(f->p[i], f->source, D);
  254. }
  255. static void DumpUpvalues (const Proto *f, DumpState *D) {
  256. int i, n;
  257. i = 0;
  258. n = f->sizeupvalues;
  259. // DumpInt(n, D);
  260. //LLOGD("LoadUpvalues %d %d", n, sizeof(Upvaldesc) * n);
  261. // size_t init_offset = fd_offset + sizeof(Upvaldesc) * f->sizeupvalues + sizeof(int);
  262. // size_t i_offset = init_offset;
  263. Upvaldesc desc;
  264. for (i = 0; i < n; i++) {
  265. desc.name = spool_add(f->upvalues[i].name);
  266. desc.idx = f->upvalues[i].idx;
  267. desc.instack = f->upvalues[i].instack;
  268. DumpBlock(&desc, sizeof(Upvaldesc), D);
  269. // if (f->upvalues[i].name) {
  270. // init_offset += fslen(f->upvalues[i].name) + 1;
  271. // //LLOGD("DumpUpvalues name %s %d %d", getstr(f->upvalues[i].name), i_offset, init_offset);
  272. // }
  273. // else {
  274. // init_offset += 1;
  275. // }
  276. }
  277. //LLOGD("DumpUpvalues Strings len %d %d %d %d", init_offset, i_offset, fd_offset, init_offset - i_offset);
  278. // DumpInt(init_offset - i_offset, D);
  279. // for (i = 0; i < n; i++) {
  280. // DumpString(f->upvalues[i].name, D);
  281. // }
  282. }
  283. static void DumpDebug (const Proto *f, DumpState *D) {
  284. int i, n;
  285. n = f->sizelineinfo;
  286. // DumpInt(n, D);
  287. DumpVector(f->lineinfo, n, D);
  288. n = f->sizelocvars;
  289. // DumpInt(n, D);
  290. // size_t init_offset = fd_offset + sizeof(LocVar) * f->sizelocvars + sizeof(int);
  291. // size_t i_offset = init_offset;
  292. LocVar lv;
  293. for (i = 0; i < n; i++) {
  294. lv.varname = spool_add(f->locvars[i].varname);
  295. lv.startpc = f->locvars[i].startpc;
  296. lv.endpc = f->locvars[i].endpc;
  297. DumpBlock(&lv, sizeof(LocVar), D);
  298. }
  299. //LLOGD("DumpDebug Strings len %d %d %d %d", init_offset, i_offset, fd_offset, init_offset - i_offset);
  300. // DumpInt(init_offset - i_offset, D);
  301. // for (i = 0; i < n; i++) {
  302. // DumpString(f->locvars[i].varname, D);
  303. // }
  304. }
  305. static void DumpFunction (const Proto *f, TString *psource, DumpState *D) {
  306. //DumpString(f->source, D);
  307. // LLOGD("<<<<<<<<< DumpFunction");
  308. DumpInt(f->linedefined, D);
  309. DumpInt(f->lastlinedefined, D);
  310. DumpByte(f->numparams, D);
  311. DumpByte(f->is_vararg, D);
  312. DumpByte(f->maxstacksize, D);
  313. DumpByte(f->source == NULL ? 0 : 1, D);
  314. LLOGD("linedefined %d", f->linedefined);
  315. LLOGD("lastlinedefined %d", f->lastlinedefined);
  316. LLOGD("numparams %d", f->numparams);
  317. LLOGD("is_vararg %d", f->is_vararg);
  318. LLOGD("maxstacksize %d", f->maxstacksize);
  319. DumpInt(f->sizecode, D);
  320. DumpInt(f->sizek, D);
  321. DumpInt(f->sizeupvalues, D);
  322. DumpInt(f->sizep, D);
  323. DumpInt(f->sizelineinfo, D);
  324. DumpInt(f->sizelocvars, D);
  325. LLOGD("sizecode %d", f->sizecode);
  326. LLOGD("sizek %d", f->sizek);
  327. LLOGD("sizeupvalues %d", f->sizeupvalues);
  328. LLOGD("sizep %d", f->sizep);
  329. LLOGD("sizelineinfo %d", f->sizelineinfo);
  330. LLOGD("sizelocvars %d", f->sizelocvars);
  331. DumpCode(f, D);
  332. DumpConstants(f, D);
  333. DumpUpvalues(f, D);
  334. DumpProtos(f, D);
  335. DumpDebug(f, D);
  336. // LLOGD(">>>>>>>>>>>>> DumpFunction");
  337. //if (f->source)
  338. // DumpString((const TString*)f->source, D);
  339. }
  340. static void DumpHeader (DumpState *D) { // 15+12
  341. DumpLiteral(LUF_SIGNATURE, D); // 4
  342. DumpByte(LUAC_VERSION, D); // 1, 5
  343. DumpByte(LUAC_FORMAT + 1, D); // 1, 6
  344. DumpLiteral(LUAC_DATA, D); // 6, 12
  345. DumpByte(sizeof(int), D); // 1, 13
  346. DumpByte(sizeof(size_t), D); // 1, 14
  347. DumpByte(sizeof(Instruction), D); // 1, 15
  348. DumpByte(sizeof(lua_Integer), D); // 1, 16
  349. DumpByte(sizeof(lua_Number), D); // 1, 17
  350. DumpInteger(LUAC_INT, D); // 4, 21
  351. DumpNumber(LUAC_NUM, D); // 4, 25
  352. }
  353. /*
  354. ** dump Lua function as precompiled chunk
  355. */
  356. int luf_dump(lua_State *L, const Proto *f, lua_Writer w, void *data,
  357. int strip, int ptroffset) {
  358. DumpState D;
  359. D.L = L;
  360. D.writer = w;
  361. D.data = data;
  362. D.strip = strip;
  363. D.status = 0;
  364. fd_offset = ptroffset;
  365. LLOGD("fd_offset %08X ptroffset %08X", fd_offset, ptroffset);
  366. // LLOGD("sizeof(Upvaldesc) %d", sizeof(Upvaldesc));
  367. // LLOGD("sizeof(LocVar) %d", sizeof(LocVar));
  368. DumpHeader(&D); // 25
  369. DumpByte(f->sizeupvalues, &D); // 1, 26
  370. size_t fill_offset = fd_offset % 0x04;
  371. LLOGD("fix %d 0x00", fill_offset);
  372. if (fill_offset != 0) {
  373. for (size_t i = 0; i < (4 - fill_offset); i++)
  374. {
  375. DumpByte(0, &D);
  376. }
  377. }
  378. LLOGD("after header + sizeupvalues, fd_offset %08X", fd_offset);
  379. size_t tcount = countProtoDumpSize(f);
  380. spool_init();
  381. str_offset = fd_offset + tcount + 4;
  382. // LLOGD("sizeupvalues %d", f->sizeupvalues);
  383. LLOGD("str_offset %08X", str_offset);
  384. LLOGD("tcount %08X ptroffset %08X", tcount, ptroffset);
  385. DumpInt(f->source == NULL ? 0 : str_offset, &D);
  386. TString* tmp = spool_add(f->source);
  387. LLOGD("source tmp %p", tmp);
  388. DumpFunction(f, NULL, &D);
  389. // LLOGD("after DumpFunction <");
  390. spool_dump(&D);
  391. // LLOGD("spool_dump <");
  392. spool_deinit();
  393. // LLOGD("spool_deinit <");
  394. LLOGD("LClosure %d Proto %d Upvaldesc %d LocVal %d",
  395. sizeof(LClosure), sizeof(Proto), sizeof(Upvaldesc), sizeof(LocVar));
  396. return D.status;
  397. }