handler.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. /*
  2. * Copyright (C) 2021 Ant Group. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include <bh_log.h>
  6. #include <handler.h>
  7. #include <limits.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include "debug_engine.h"
  11. #include "packets.h"
  12. #include "utils.h"
  13. #include "wasm_runtime.h"
  14. #define MAX_PACKET_SIZE (0x20000)
  15. static char tmpbuf[MAX_PACKET_SIZE];
  16. void
  17. handle_generay_set(WASMGDBServer *server, char *payload)
  18. {
  19. const char *name;
  20. char *args;
  21. args = strchr(payload, ':');
  22. if (args)
  23. *args++ = '\0';
  24. name = payload;
  25. LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
  26. if (!strcmp(name, "StartNoAckMode")) {
  27. server->noack = true;
  28. write_packet(server, "OK");
  29. }
  30. if (!strcmp(name, "ThreadSuffixSupported")) {
  31. write_packet(server, "");
  32. }
  33. if (!strcmp(name, "ListThreadsInStopReply")) {
  34. write_packet(server, "");
  35. }
  36. if (!strcmp(name, "EnableErrorStrings")) {
  37. write_packet(server, "OK");
  38. }
  39. }
  40. static void
  41. process_xfer(WASMGDBServer *server, const char *name, char *args)
  42. {
  43. const char *mode = args;
  44. args = strchr(args, ':');
  45. if (args)
  46. *args++ = '\0';
  47. if (!strcmp(name, "libraries") && !strcmp(mode, "read")) {
  48. //TODO: how to get current wasm file name?
  49. uint64_t addr = wasm_debug_instance_get_load_addr(
  50. (WASMDebugInstance *)server->thread->debug_instance);
  51. #if WASM_ENABLE_LIBC_WASI != 0
  52. char objname[128];
  53. wasm_debug_instance_get_current_object_name(
  54. (WASMDebugInstance *)server->thread->debug_instance, objname, 128);
  55. sprintf(tmpbuf,
  56. "l<library-list><library name=\"%s\"><section "
  57. "address=\"0x%lx\"/></library></library-list>",
  58. objname, addr);
  59. #else
  60. sprintf(tmpbuf,
  61. "l<library-list><library name=\"%s\"><section "
  62. "address=\"0x%lx\"/></library></library-list>",
  63. "nobody.wasm", addr);
  64. #endif
  65. write_packet(server, tmpbuf);
  66. }
  67. }
  68. void
  69. porcess_wasm_local(WASMGDBServer *server, char *args)
  70. {
  71. int frame_index;
  72. int local_index;
  73. char buf[16];
  74. int size = 16;
  75. bool ret;
  76. sprintf(tmpbuf, "E01");
  77. if (sscanf(args, "%d;%d", &frame_index, &local_index) == 2) {
  78. ret = wasm_debug_instance_get_local(
  79. (WASMDebugInstance *)server->thread->debug_instance, frame_index,
  80. local_index, buf, &size);
  81. if (ret && size > 0) {
  82. mem2hex(buf, tmpbuf, size);
  83. }
  84. }
  85. write_packet(server, tmpbuf);
  86. }
  87. void
  88. porcess_wasm_global(WASMGDBServer *server, char *args)
  89. {
  90. int frame_index;
  91. int global_index;
  92. char buf[16];
  93. int size = 16;
  94. bool ret;
  95. sprintf(tmpbuf, "E01");
  96. if (sscanf(args, "%d;%d", &frame_index, &global_index) == 2) {
  97. ret = wasm_debug_instance_get_global(
  98. (WASMDebugInstance *)server->thread->debug_instance, frame_index,
  99. global_index, buf, &size);
  100. if (ret && size > 0) {
  101. mem2hex(buf, tmpbuf, size);
  102. }
  103. }
  104. write_packet(server, tmpbuf);
  105. }
  106. void
  107. handle_generay_query(WASMGDBServer *server, char *payload)
  108. {
  109. const char *name;
  110. char *args;
  111. args = strchr(payload, ':');
  112. if (args)
  113. *args++ = '\0';
  114. name = payload;
  115. LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
  116. if (!strcmp(name, "C")) {
  117. uint64_t pid, tid;
  118. pid = wasm_debug_instance_get_pid(
  119. (WASMDebugInstance *)server->thread->debug_instance);
  120. tid = wasm_debug_instance_get_tid(
  121. (WASMDebugInstance *)server->thread->debug_instance);
  122. snprintf(tmpbuf, sizeof(tmpbuf), "QCp%lx.%lx", pid, tid);
  123. write_packet(server, tmpbuf);
  124. }
  125. if (!strcmp(name, "Supported")) {
  126. sprintf(tmpbuf, "qXfer:libraries:read+;PacketSize=%x;", MAX_PACKET_SIZE);
  127. write_packet(server, tmpbuf);
  128. }
  129. if (!strcmp(name, "Xfer")) {
  130. name = args;
  131. if (!args) {
  132. LOG_ERROR("payload parse error during handle_generay_query");
  133. return;
  134. }
  135. args = strchr(args, ':');
  136. if (args) {
  137. *args++ = '\0';
  138. process_xfer(server, name, args);
  139. }
  140. }
  141. if (!strcmp(name, "HostInfo")) {
  142. //Todo: change vendor to Intel for outside tree?
  143. char triple[256];
  144. mem2hex("wasm32-Ant-wasi-wasm", triple,
  145. strlen("wasm32-Ant-wasi-wasm"));
  146. sprintf(tmpbuf,
  147. "vendor:Ant;ostype:wasi;arch:wasm32;"
  148. "triple:%s;endian:little;ptrsize:4;",
  149. triple);
  150. write_packet(server, tmpbuf);
  151. }
  152. if (!strcmp(name, "GetWorkingDir")) {
  153. if (getcwd(tmpbuf, PATH_MAX))
  154. write_packet(server, tmpbuf);
  155. }
  156. if (!strcmp(name, "QueryGDBServer")) {
  157. write_packet(server, "");
  158. }
  159. if (!strcmp(name, "VAttachOrWaitSupported")) {
  160. write_packet(server, "");
  161. }
  162. if (!strcmp(name, "ProcessInfo")) {
  163. //Todo: process id parent-pid
  164. uint64_t pid;
  165. pid = wasm_debug_instance_get_pid(
  166. (WASMDebugInstance *)server->thread->debug_instance);
  167. char triple[256];
  168. //arch-vendor-os-env(format)
  169. mem2hex("wasm32-Ant-wasi-wasm", triple,
  170. strlen("wasm32-Ant-wasi-wasm"));
  171. sprintf(tmpbuf,
  172. "pid:%lx;parent-pid:%lx;vendor:Ant;ostype:wasi;arch:wasm32;"
  173. "triple:%s;endian:little;ptrsize:4;",
  174. pid, pid, triple);
  175. write_packet(server, tmpbuf);
  176. }
  177. if (!strcmp(name, "RegisterInfo0")) {
  178. sprintf(
  179. tmpbuf,
  180. "name:pc;alt-name:pc;bitsize:64;offset:0;encoding:uint;format:hex;"
  181. "set:General Purpose Registers;gcc:16;dwarf:16;generic:pc;");
  182. write_packet(server, tmpbuf);
  183. }
  184. else if (!strncmp(name, "RegisterInfo", strlen("RegisterInfo"))) {
  185. write_packet(server, "E45");
  186. }
  187. if (!strcmp(name, "StructuredDataPlugins")) {
  188. write_packet(server, "");
  189. }
  190. if (args && (!strcmp(name, "MemoryRegionInfo"))) {
  191. uint64_t addr = strtol(args, NULL, 16);
  192. WASMDebugMemoryInfo *mem_info = wasm_debug_instance_get_memregion(
  193. (WASMDebugInstance *)server->thread->debug_instance, addr);
  194. if (mem_info) {
  195. char name[256];
  196. mem2hex(mem_info->name, name, strlen(mem_info->name));
  197. sprintf(tmpbuf, "start:%lx;size:%lx;permissions:%s;name:%s;",
  198. (uint64)mem_info->start, mem_info->size, mem_info->permisson, name);
  199. write_packet(server, tmpbuf);
  200. wasm_debug_instance_destroy_memregion(
  201. (WASMDebugInstance *)server->thread->debug_instance, mem_info);
  202. }
  203. }
  204. if (!strcmp(name, "WasmData")) {
  205. }
  206. if (!strcmp(name, "WasmMem")) {
  207. }
  208. if (!strcmp(name, "Symbol")) {
  209. write_packet(server, "");
  210. }
  211. if (args && (!strcmp(name, "WasmCallStack"))) {
  212. uint64_t tid = strtol(args, NULL, 16);
  213. uint64_t buf[1024 / sizeof(uint64_t)];
  214. uint64_t count = wasm_debug_instance_get_call_stack_pcs(
  215. (WASMDebugInstance *)server->thread->debug_instance, tid, buf,
  216. 1024 / sizeof(uint64_t));
  217. if (count > 0) {
  218. mem2hex((char *)buf, tmpbuf, count * sizeof(uint64_t));
  219. write_packet(server, tmpbuf);
  220. }
  221. else
  222. write_packet(server, "");
  223. }
  224. if (args && (!strcmp(name, "WasmLocal"))) {
  225. porcess_wasm_local(server, args);
  226. }
  227. if (args && (!strcmp(name, "WasmGlobal"))) {
  228. porcess_wasm_global(server, args);
  229. }
  230. }
  231. static void
  232. send_thread_stop_status(WASMGDBServer *server, uint32_t status, uint64_t tid)
  233. {
  234. int tids_number, len = 0, i = 0;
  235. uint64_t tids[20];
  236. char pc_string[17];
  237. uint32_t gdb_status = status;
  238. if (status == 0) {
  239. sprintf(tmpbuf, "W%02x", status);
  240. write_packet(server, tmpbuf);
  241. return;
  242. }
  243. tids_number = wasm_debug_instance_get_tids(
  244. (WASMDebugInstance *)server->thread->debug_instance, tids, 20);
  245. uint64_t pc = wasm_debug_instance_get_pc(
  246. (WASMDebugInstance *)server->thread->debug_instance);
  247. if (status == WAMR_SIG_SINGSTEP) {
  248. gdb_status = WAMR_SIG_TRAP;
  249. }
  250. //TODO: how name a wasm thread?
  251. len += sprintf(tmpbuf, "T%02xthread:%lx;name:%s;", gdb_status, tid, "nobody");
  252. if (tids_number > 0) {
  253. len += sprintf(tmpbuf + len, "threads:");
  254. while (i < tids_number) {
  255. if (i == tids_number - 1)
  256. len += sprintf(tmpbuf + len, "%lx;", tids[i]);
  257. else
  258. len += sprintf(tmpbuf + len, "%lx,", tids[i]);
  259. i++;
  260. }
  261. }
  262. mem2hex((void *)&pc, pc_string, 8);
  263. pc_string[8 * 2] = '\0';
  264. if (status == WAMR_SIG_TRAP) {
  265. len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
  266. pc_string, "breakpoint");
  267. }
  268. else if (status == WAMR_SIG_SINGSTEP) {
  269. len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
  270. pc_string, "trace");
  271. }
  272. else if (status > 0) {
  273. len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
  274. pc_string, "signal");
  275. }
  276. write_packet(server, tmpbuf);
  277. }
  278. void
  279. handle_v_packet(WASMGDBServer *server, char *payload)
  280. {
  281. const char *name;
  282. char *args;
  283. uint32_t status;
  284. args = strchr(payload, ';');
  285. if (args)
  286. *args++ = '\0';
  287. name = payload;
  288. LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
  289. if (!strcmp("Cont?", name))
  290. write_packet(server, "vCont;c;C;s;S;");
  291. if (!strcmp("Cont", name)) {
  292. if (args && args[0] == 's') {
  293. char *numstring = strchr(args, ':');
  294. if (numstring) {
  295. *numstring++ = '\0';
  296. uint64_t tid = strtol(numstring, NULL, 16);
  297. wasm_debug_instance_set_cur_thread(
  298. (WASMDebugInstance *)server->thread->debug_instance, tid);
  299. wasm_debug_instance_singlestep(
  300. (WASMDebugInstance *)server->thread->debug_instance, tid);
  301. tid = wasm_debug_instance_wait_thread(
  302. (WASMDebugInstance *)server->thread->debug_instance, tid,
  303. &status);
  304. send_thread_stop_status(server, status, tid);
  305. }
  306. }
  307. }
  308. }
  309. void
  310. handle_threadstop_request(WASMGDBServer *server, char *payload)
  311. {
  312. uint64_t tid = wasm_debug_instance_get_tid(
  313. (WASMDebugInstance *)server->thread->debug_instance);
  314. uint32_t status;
  315. tid = wasm_debug_instance_wait_thread(
  316. (WASMDebugInstance *)server->thread->debug_instance, tid, &status);
  317. send_thread_stop_status(server, status, tid);
  318. }
  319. void
  320. handle_set_current_thread(WASMGDBServer *server, char *payload)
  321. {
  322. LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload, payload);
  323. if ('g' == *payload++) {
  324. uint64_t tid;
  325. tid = strtol(payload, NULL, 16);
  326. if (tid > 0)
  327. wasm_debug_instance_set_cur_thread(
  328. (WASMDebugInstance *)server->thread->debug_instance, tid);
  329. }
  330. write_packet(server, "OK");
  331. }
  332. void
  333. handle_get_register(WASMGDBServer *server, char *payload)
  334. {
  335. int i = strtol(payload, NULL, 16);
  336. if (i != 0) {
  337. write_packet(server, "E01");
  338. return;
  339. }
  340. uint64_t regdata = wasm_debug_instance_get_pc(
  341. (WASMDebugInstance *)server->thread->debug_instance);
  342. mem2hex((void *)&regdata, tmpbuf, 8);
  343. tmpbuf[8 * 2] = '\0';
  344. write_packet(server, tmpbuf);
  345. }
  346. void
  347. handle_get_json_request(WASMGDBServer *server, char *payload)
  348. {
  349. char *args;
  350. args = strchr(payload, ':');
  351. if (args)
  352. *args++ = '\0';
  353. write_packet(server, "");
  354. }
  355. void
  356. handle_get_read_binary_memory(WASMGDBServer *server, char *payload)
  357. {
  358. write_packet(server, "");
  359. }
  360. void
  361. handle_get_read_memory(WASMGDBServer *server, char *payload)
  362. {
  363. size_t maddr, mlen;
  364. bool ret;
  365. sprintf(tmpbuf, "%s", "");
  366. if (sscanf(payload, "%zx,%zx", &maddr, &mlen) == 2) {
  367. if (mlen * 2 > MAX_PACKET_SIZE) {
  368. LOG_ERROR("Buffer overflow!");
  369. mlen = MAX_PACKET_SIZE / 2;
  370. }
  371. char *buff = wasm_runtime_malloc(mlen);
  372. if (buff) {
  373. ret = wasm_debug_instance_get_mem(
  374. (WASMDebugInstance *)server->thread->debug_instance, maddr, buff,
  375. &mlen);
  376. if (ret) {
  377. mem2hex(buff, tmpbuf, mlen);
  378. }
  379. wasm_runtime_free(buff);
  380. }
  381. }
  382. write_packet(server, tmpbuf);
  383. }
  384. void
  385. handle_get_write_memory(WASMGDBServer *server, char *payload)
  386. {
  387. size_t maddr, mlen, hex_len;
  388. int offset, act_len;
  389. char *buff;
  390. bool ret;
  391. sprintf(tmpbuf, "%s", "");
  392. if (sscanf(payload, "%zx,%zx:%n", &maddr, &mlen, &offset) == 2) {
  393. payload += offset;
  394. hex_len = strlen(payload);
  395. act_len = hex_len / 2 < mlen ? hex_len / 2 : mlen;
  396. buff = wasm_runtime_malloc(act_len);
  397. if (buff) {
  398. hex2mem(payload, buff, act_len);
  399. ret = wasm_debug_instance_set_mem(
  400. (WASMDebugInstance *)server->thread->debug_instance, maddr, buff,
  401. &mlen);
  402. if (ret) {
  403. sprintf(tmpbuf, "%s", "OK");
  404. }
  405. wasm_runtime_free(buff);
  406. }
  407. }
  408. write_packet(server, tmpbuf);
  409. }
  410. void
  411. handle_add_break(WASMGDBServer *server, char *payload)
  412. {
  413. size_t type, addr, length;
  414. if (sscanf(payload, "%zx,%zx,%zx", &type, &addr, &length) == 3) {
  415. if (type == eBreakpointSoftware) {
  416. bool ret = wasm_debug_instance_add_breakpoint(
  417. (WASMDebugInstance *)server->thread->debug_instance, addr,
  418. length);
  419. if (ret)
  420. write_packet(server, "OK");
  421. else
  422. write_packet(server, "E01");
  423. return;
  424. }
  425. }
  426. write_packet(server, "");
  427. }
  428. void
  429. handle_remove_break(WASMGDBServer *server, char *payload)
  430. {
  431. size_t type, addr, length;
  432. if (sscanf(payload, "%zx,%zx,%zx", &type, &addr, &length) == 3) {
  433. if (type == eBreakpointSoftware) {
  434. bool ret = wasm_debug_instance_remove_breakpoint(
  435. (WASMDebugInstance *)server->thread->debug_instance, addr,
  436. length);
  437. if (ret)
  438. write_packet(server, "OK");
  439. else
  440. write_packet(server, "E01");
  441. return;
  442. }
  443. }
  444. write_packet(server, "");
  445. }
  446. void
  447. handle_continue_request(WASMGDBServer *server, char *payload)
  448. {
  449. uint64_t tid;
  450. uint32_t status;
  451. wasm_debug_instance_continue(
  452. (WASMDebugInstance *)server->thread->debug_instance);
  453. tid = wasm_debug_instance_get_tid(
  454. (WASMDebugInstance *)server->thread->debug_instance);
  455. tid = wasm_debug_instance_wait_thread(
  456. (WASMDebugInstance *)server->thread->debug_instance, tid, &status);
  457. send_thread_stop_status(server, status, tid);
  458. }
  459. void
  460. handle_kill_request(WASMGDBServer *server, char *payload)
  461. {
  462. uint64_t tid;
  463. uint32_t status;
  464. wasm_debug_instance_kill(
  465. (WASMDebugInstance *)server->thread->debug_instance);
  466. tid = wasm_debug_instance_get_tid(
  467. (WASMDebugInstance *)server->thread->debug_instance);
  468. tid = wasm_debug_instance_wait_thread(
  469. (WASMDebugInstance *)server->thread->debug_instance, tid, &status);
  470. send_thread_stop_status(server, status, tid);
  471. }
  472. static void
  473. handle_malloc(WASMGDBServer *server, char *payload)
  474. {
  475. char *args;
  476. uint64_t size;
  477. int map_port = MMAP_PROT_NONE;
  478. uint64_t addr;
  479. sprintf(tmpbuf, "%s", "E03");
  480. args = strstr(payload, ",");
  481. if (args) {
  482. *args++ = '\0';
  483. }
  484. else {
  485. LOG_ERROR("Payload parse error during handle malloc");
  486. return;
  487. }
  488. size = strtol(payload, NULL, 16);
  489. if (size > 0) {
  490. while (*args) {
  491. if (*args == 'r') {
  492. map_port |= MMAP_PROT_READ;
  493. }
  494. if (*args == 'w') {
  495. map_port |= MMAP_PROT_WRITE;
  496. }
  497. if (*args == 'x') {
  498. map_port |= MMAP_PROT_EXEC;
  499. }
  500. args++;
  501. }
  502. addr = wasm_debug_instance_mmap(
  503. (WASMDebugInstance *)server->thread->debug_instance, size, map_port);
  504. if (addr) {
  505. sprintf(tmpbuf, "%lx", addr);
  506. }
  507. }
  508. write_packet(server, tmpbuf);
  509. }
  510. static void
  511. handle_free(WASMGDBServer *server, char *payload)
  512. {
  513. uint64_t addr;
  514. bool ret;
  515. sprintf(tmpbuf, "%s", "E03");
  516. addr = strtol(payload, NULL, 16);
  517. ret = wasm_debug_instance_ummap(
  518. (WASMDebugInstance *)server->thread->debug_instance, addr);
  519. if (ret) {
  520. sprintf(tmpbuf, "%s", "OK");
  521. }
  522. write_packet(server, tmpbuf);
  523. }
  524. void
  525. handle____request(WASMGDBServer *server, char *payload)
  526. {
  527. char *args;
  528. if (payload[0] == 'M') {
  529. args = payload + 1;
  530. handle_malloc(server, args);
  531. }
  532. if (payload[0] == 'm') {
  533. args = payload + 1;
  534. handle_free(server, args);
  535. }
  536. }