luat_cmds.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. #include "luat_base.h"
  2. #include "luat_fs.h"
  3. #include "luat_malloc.h"
  4. #include "lundump.h"
  5. #include "luat_mock.h"
  6. #include "luat_luadb2.h"
  7. #define LUAT_LOG_TAG "fs"
  8. #include "luat_log.h"
  9. #include "dirent.h"
  10. extern int cmdline_argc;
  11. extern char **cmdline_argv;
  12. // luadb数据的上下文
  13. luat_luadb2_ctx_t luadb_ctx = {0};
  14. char *luadb_ptr;
  15. // 导出luadb数据的路径,默认是导出
  16. char luadb_dump_path[1024];
  17. // 脚本lua文件转luac时,是否删除调试信息,默认不删
  18. int cfg_luac_strip;
  19. int cfg_dump_luadb;
  20. int cfg_dump_report;
  21. int cfg_norun;
  22. void *check_file_path(const char *path);
  23. static int luat_cmd_load_luadb(const char *path);
  24. static int luat_cmd_load_luatools(const char *path);
  25. int luadb_do_report(luat_luadb2_ctx_t *ctx);
  26. static int is_opts(const char *key, const char *arg)
  27. {
  28. if (strlen(key) >= strlen(arg))
  29. {
  30. return 0;
  31. }
  32. return memcmp(key, arg, strlen(key)) == 0;
  33. }
  34. int luat_cmd_parse(int argc, char **argv)
  35. {
  36. if (cmdline_argc == 1)
  37. {
  38. return 0;
  39. }
  40. luat_luadb2_init(&luadb_ctx);
  41. for (size_t i = 1; i < (size_t)argc; i++)
  42. {
  43. const char *arg = argv[i];
  44. // 加载luadb文件镜像直接启动
  45. if (is_opts("--load_luadb=", arg))
  46. {
  47. if (luat_cmd_load_luadb(arg + strlen("--load_luadb=")))
  48. {
  49. LLOGE("加载luadb镜像失败");
  50. return -1;
  51. }
  52. continue;
  53. }
  54. if (is_opts("--ldb=", arg))
  55. {
  56. if (luat_cmd_load_luadb(arg + strlen("--ldb=")))
  57. {
  58. LLOGE("加载luadb镜像失败");
  59. return -1;
  60. }
  61. continue;
  62. }
  63. // 加载LuaTools项目文件直接启动
  64. if (is_opts("--load_luatools=", arg))
  65. {
  66. if (luat_cmd_load_luatools(arg + strlen("--load_luatools=")))
  67. {
  68. LLOGE("加载luatools项目文件失败");
  69. return -1;
  70. }
  71. continue;
  72. }
  73. if (is_opts("--llt=", arg))
  74. {
  75. if (luat_cmd_load_luatools(arg + strlen("--llt=")))
  76. {
  77. LLOGE("加载luatools项目文件失败");
  78. return -1;
  79. }
  80. continue;
  81. }
  82. // mock加载
  83. if (is_opts("--mlua=", arg))
  84. {
  85. if (luat_mock_init(arg + strlen("--mlua=")))
  86. {
  87. LLOGE("加载mock功能失败");
  88. return -1;
  89. }
  90. continue;
  91. }
  92. // 导出luadb文件
  93. if (is_opts("--dump_luadb=", arg))
  94. {
  95. memcpy(luadb_dump_path, arg + strlen("--dump_luadb="), strlen(arg) - strlen("--dump_luadb="));
  96. continue;
  97. }
  98. if (is_opts("--luac_strip=", arg))
  99. {
  100. if (!strcmp("--luac_strip=1", arg)) {
  101. cfg_luac_strip = 1;
  102. }
  103. else if (!strcmp("--luac_strip=0", arg)) {
  104. cfg_luac_strip = 0;
  105. }
  106. else if (!strcmp("--luac_strip=2", arg)) {
  107. cfg_luac_strip = 2;
  108. }
  109. continue;
  110. }
  111. if (is_opts("--luac_report=", arg))
  112. {
  113. // LLOGD("只导出luadb数据");
  114. if (!strcmp("--luac_report=1", arg)) {
  115. cfg_dump_report = 1;
  116. }
  117. continue;
  118. }
  119. // 是否导出luadb文件
  120. if (is_opts("--norun=", arg))
  121. {
  122. // LLOGD("只导出luadb数据");
  123. if (!strcmp("--norun=1", arg)) {
  124. cfg_norun = 1;
  125. }
  126. continue;
  127. }
  128. if (arg[0] == '-')
  129. {
  130. continue;
  131. }
  132. check_file_path(arg);
  133. }
  134. if (luadb_dump_path[0]) {
  135. LLOGD("导出luadb数据到 %s 大小 %d", luadb_dump_path, luadb_ctx.offset);
  136. FILE* f = fopen(luadb_dump_path, "wb+");
  137. if (f == NULL) {
  138. LLOGE("无法打开luadb导出路径 %s", luadb_dump_path);
  139. exit(1);
  140. }
  141. fwrite(luadb_ptr, 1, luadb_ctx.offset, f);
  142. fclose(f);
  143. }
  144. if (cfg_norun) {
  145. exit(0);
  146. }
  147. return 0;
  148. }
  149. static int luat_cmd_load_luadb(const char *path)
  150. {
  151. long len = 0;
  152. FILE *f = fopen(path, "rb");
  153. if (!f)
  154. {
  155. LLOGE("无法打开luadb镜像文件 %s", path);
  156. return -1;
  157. }
  158. fseek(f, 0, SEEK_END);
  159. len = ftell(f);
  160. fseek(f, 0, SEEK_SET);
  161. char *ptr = luat_heap_malloc(len);
  162. if (ptr == NULL)
  163. {
  164. fclose(f);
  165. LLOGE("luadb镜像文件太大,内存放不下 %s", path);
  166. return -1;
  167. }
  168. fread(ptr, len, 1, f);
  169. fclose(f);
  170. luadb_ptr = ptr;
  171. // luadb_offset = len;
  172. return 0;
  173. }
  174. static int luat_cmd_load_luatools(const char *path)
  175. {
  176. long len = 0;
  177. FILE *f = fopen(path, "rb");
  178. if (!f)
  179. {
  180. LLOGE("无法打开luatools项目文件 %s", path);
  181. return -1;
  182. }
  183. fseek(f, 0, SEEK_END);
  184. len = ftell(f);
  185. fseek(f, 0, SEEK_SET);
  186. char *ptr = luat_heap_malloc(len + 1);
  187. if (ptr == NULL)
  188. {
  189. fclose(f);
  190. LLOGE("luatools项目文件太大,内存放不下 %s", path);
  191. return -1;
  192. }
  193. fread(ptr, len, 1, f);
  194. fclose(f);
  195. ptr[len] = 0;
  196. char *ret = ptr;
  197. char dirline[512] = {0};
  198. char rpath[1024] = {0};
  199. size_t retlen = 0;
  200. while (ptr[0] != 0x00)
  201. {
  202. // LLOGD("ptr %c", ptr[0]);
  203. if (ptr[0] == '\r' || ptr[0] == '\n')
  204. {
  205. if (ret != ptr)
  206. {
  207. ptr[0] = 0x00;
  208. retlen = strlen(ret);
  209. // LLOGD("检索到的行 %s", ret);
  210. if (!strcmp("[info]", ret))
  211. {
  212. }
  213. else if (retlen > 5)
  214. {
  215. if (ret[0] == '[' && ret[retlen - 1] == ']')
  216. {
  217. LLOGD("目录行 %s", ret);
  218. memcpy(dirline, ret + 1, retlen - 2);
  219. dirline[retlen - 2] = 0x00;
  220. }
  221. else
  222. {
  223. if (dirline[0])
  224. {
  225. for (size_t i = 0; i < strlen(ret); i++)
  226. {
  227. if (ret[i] == ' ' || ret[i] == '=')
  228. {
  229. ret[i] = 0;
  230. memset(rpath, 0, 1024);
  231. memcpy(rpath, dirline, strlen(dirline));
  232. #ifdef LUA_USE_WINDOWS
  233. rpath[strlen(dirline)] = '\\';
  234. #else
  235. rpath[strlen(dirline)] = '/';
  236. #endif
  237. memcpy(rpath + strlen(rpath), ret, strlen(ret));
  238. LLOGI("加载文件 %s", rpath);
  239. if (check_file_path(rpath) == NULL)
  240. return -2;
  241. break;
  242. }
  243. }
  244. }
  245. }
  246. }
  247. }
  248. ret = ptr + 1;
  249. }
  250. ptr++;
  251. }
  252. return 0;
  253. }
  254. typedef struct luac_ctx
  255. {
  256. char *ptr;
  257. size_t len;
  258. } luac_ctx_t;
  259. luac_ctx_t* last_ctx = NULL;
  260. static int writer(lua_State *L, const void *p, size_t size, void *u)
  261. {
  262. UNUSED(L);
  263. // LLOGD("写入部分数据 %p %d", p, size);
  264. luac_ctx_t *ctx = (luac_ctx_t *)u;
  265. if (ctx->ptr == NULL)
  266. {
  267. ctx->ptr = luat_heap_malloc(size);
  268. ctx->len = size;
  269. memcpy(ctx->ptr, p, size);
  270. return 0;
  271. }
  272. char *ptr = luat_heap_realloc(ctx->ptr, ctx->len + size);
  273. if (ptr == NULL)
  274. {
  275. LLOGE("内存分配失败");
  276. return 1;
  277. }
  278. memcpy(ptr + ctx->len, p, size);
  279. ctx->ptr = ptr;
  280. ctx->len += size;
  281. return 0;
  282. }
  283. static int pmain(lua_State *L)
  284. {
  285. const char *name = luaL_checkstring(L, 1);
  286. size_t len = 0;
  287. const char *data = luaL_checklstring(L, 2, &len);
  288. int ret = luaL_loadbufferx(L, data, len, name, NULL);
  289. if (ret)
  290. {
  291. LLOGE("文件加载失败 %s %s", name, lua_tostring(L, -1));
  292. return 0;
  293. }
  294. // LLOGD("luac转换成功,开始转buff %s", name);
  295. luac_ctx_t *ctx = luat_heap_malloc(sizeof(luac_ctx_t));
  296. memset(ctx, 0, sizeof(luac_ctx_t));
  297. // LLOGD("getproto ");
  298. const Proto *f = getproto(L->top - 1);
  299. // LLOGD("Proto %p", f);
  300. if (cfg_luac_strip) {
  301. if (cfg_luac_strip == 1 && !strcmp("main.lua", name)) {
  302. ret = luaU_dump(L, f, writer, ctx, 0);
  303. }
  304. else {
  305. ret = luaU_dump(L, f, writer, ctx, 1);
  306. }
  307. }
  308. else {
  309. ret = luaU_dump(L, f, writer, ctx, 0);
  310. }
  311. // LLOGD("luaU_dump 执行完成");
  312. if (ret == 0)
  313. {
  314. // luadb_addfile(name, ctx->ptr, ctx->len);
  315. luat_luadb2_write(&luadb_ctx, name, ctx->ptr, ctx->len);
  316. luadb_ptr = luadb_ctx.dataptr;
  317. }
  318. lua_pushinteger(L, ret);
  319. luat_heap_free(ctx->ptr);
  320. luat_heap_free(ctx);
  321. return 1;
  322. }
  323. static int to_luac(const char *fullpath, const char *name, char *data, size_t len)
  324. {
  325. // LLOGD("检查语法并转换成luac %s 路径 %s", name, fullpath);
  326. lua_State *L = lua_newstate(luat_heap_alloc, NULL);
  327. // LLOGD("创建临时luavm");
  328. lua_pushcfunction(L, &pmain);
  329. lua_pushstring(L, name);
  330. lua_pushlstring(L, data, len);
  331. // LLOGD("准备执行luac转换");
  332. int ret = lua_pcall(L, 2, 1, 0);
  333. if (ret)
  334. {
  335. LLOGD("lua文件加载失败 %s %d", fullpath, ret);
  336. lua_close(L);
  337. return -1;
  338. }
  339. ret = luaL_checkinteger(L, -1);
  340. lua_close(L);
  341. return ret;
  342. }
  343. static int add_onefile(const char *path)
  344. {
  345. size_t len = 0;
  346. int ret = 0;
  347. // LLOGD("把%s当做main.lua运行", path);
  348. char tmpname[512] = {0};
  349. FILE *f = fopen(path, "rb");
  350. if (!f)
  351. {
  352. LLOGE("文件不存在 %s", path);
  353. return -1;
  354. }
  355. fseek(f, 0, SEEK_END);
  356. len = ftell(f);
  357. fseek(f, 0, SEEK_SET);
  358. // void* fptr = luat_heap_malloc(len);
  359. char *tmp = luat_heap_malloc(len);
  360. if (tmp == NULL)
  361. {
  362. fclose(f);
  363. LLOGE("文件太大,内存放不下 %s", path);
  364. return -2;
  365. }
  366. fread(tmp, 1, len, f);
  367. fclose(f);
  368. for (size_t i = strlen(path); i > 0; i--)
  369. {
  370. if (path[i - 1] == '/' || path[i - 1] == '\\')
  371. {
  372. memcpy(tmpname, path + i, strlen(path) - 1);
  373. break;
  374. }
  375. }
  376. if (tmpname[0] == 0x00)
  377. {
  378. memcpy(tmpname, path, strlen(path));
  379. }
  380. if (!memcmp(path + strlen(path) - 4, ".lua", 4))
  381. {
  382. ret = to_luac(path, tmpname, tmp, len);
  383. }
  384. else
  385. {
  386. // ret = luadb_addfile(tmpname, tmp, len);
  387. ret = luat_luadb2_write(&luadb_ctx, tmpname, tmp, len);
  388. luadb_ptr = luadb_ctx.dataptr;
  389. }
  390. luat_heap_free(tmp);
  391. return ret;
  392. }
  393. void *check_file_path(const char *path)
  394. {
  395. if (strlen(path) < 4 || strlen(path) >= 512)
  396. {
  397. LLOGD("文件长度不对劲 %d %s", strlen(path), path);
  398. return NULL;
  399. }
  400. // 目录模式
  401. if (!memcmp(path + strlen(path) - 1, "/", 1) || !memcmp(path + strlen(path) - 1, "\\", 1))
  402. {
  403. DIR *dp;
  404. struct dirent *ep;
  405. // int index = 0;
  406. char buff[512] = {0};
  407. // LLOGD("加载目录 %s", path);
  408. #ifdef LUA_USE_WINDOWS
  409. memcpy(buff, path, strlen(path));
  410. #else
  411. memcpy(buff, path, strlen(path) - 1);
  412. #endif;
  413. dp = opendir(buff);
  414. // LLOGD("目录打开 %p", dp);
  415. if (dp != NULL)
  416. {
  417. // LLOGD("开始遍历目录 %s", path);
  418. while ((ep = readdir(dp)) != NULL)
  419. {
  420. // LLOGD("文件/目录 %s %d", ep->d_name, ep->d_type);
  421. if (ep->d_type != DT_REG)
  422. {
  423. continue;
  424. }
  425. #ifdef LUA_USE_WINDOWS
  426. sprintf(buff, "%s\\%s", path, ep->d_name);
  427. #else
  428. sprintf(buff, "%s/%s", path, ep->d_name);
  429. #endif
  430. if (add_onefile(buff))
  431. {
  432. return NULL;
  433. }
  434. }
  435. // LLOGD("遍历结束");
  436. (void)closedir(dp);
  437. return luadb_ptr;
  438. }
  439. else
  440. {
  441. LLOGW("opendir file %s failed", path);
  442. return NULL;
  443. }
  444. }
  445. else
  446. {
  447. if (add_onefile(path))
  448. {
  449. return NULL;
  450. }
  451. return luadb_ptr;
  452. }
  453. // return NULL;
  454. }
  455. // 加载并分析文件
  456. int luat_cmd_load_and_analyse(const char *path)
  457. {
  458. size_t len = 0;
  459. int ret = 0;
  460. // LLOGD("把%s当做main.lua运行", path);
  461. char tmpname[512] = {0};
  462. FILE *f = fopen(path, "rb");
  463. if (!f)
  464. {
  465. LLOGE("文件不存在 %s", path);
  466. return -1;
  467. }
  468. fseek(f, 0, SEEK_END);
  469. len = ftell(f);
  470. fseek(f, 0, SEEK_SET);
  471. // void* fptr = luat_heap_malloc(len);
  472. char *tmp = luat_heap_malloc(len);
  473. if (tmp == NULL)
  474. {
  475. fclose(f);
  476. LLOGE("文件太大,内存放不下 %s", path);
  477. return -2;
  478. }
  479. fread(tmp, 1, len, f);
  480. fclose(f);
  481. for (size_t i = strlen(path); i > 0; i--)
  482. {
  483. if (path[i - 1] == '/' || path[i - 1] == '\\')
  484. {
  485. memcpy(tmpname, path + i, strlen(path) - 1);
  486. break;
  487. }
  488. }
  489. if (tmpname[0] == 0x00)
  490. {
  491. memcpy(tmpname, path, strlen(path));
  492. }
  493. if (!memcmp(path + strlen(path) - 4, ".lua", 4))
  494. {
  495. ret = to_luac(path, tmpname, tmp, len);
  496. }
  497. else
  498. {
  499. // ret = luadb_addfile(tmpname, tmp, len);
  500. ret = luat_luadb2_write(&luadb_ctx, tmpname, tmp, len);
  501. luadb_ptr = luadb_ctx.dataptr;
  502. }
  503. luat_heap_free(tmp);
  504. return ret;
  505. }