handler.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  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;",
  127. MAX_PACKET_SIZE);
  128. write_packet(server, tmpbuf);
  129. }
  130. if (!strcmp(name, "Xfer")) {
  131. name = args;
  132. if (!args) {
  133. LOG_ERROR("payload parse error during handle_generay_query");
  134. return;
  135. }
  136. args = strchr(args, ':');
  137. if (args) {
  138. *args++ = '\0';
  139. process_xfer(server, name, args);
  140. }
  141. }
  142. if (!strcmp(name, "HostInfo")) {
  143. // Todo: change vendor to Intel for outside tree?
  144. char triple[256];
  145. mem2hex("wasm32-Ant-wasi-wasm", triple, 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, "ModuleInfo")) {
  153. write_packet(server, "");
  154. }
  155. if (!strcmp(name, "GetWorkingDir")) {
  156. if (getcwd(tmpbuf, PATH_MAX))
  157. write_packet(server, tmpbuf);
  158. }
  159. if (!strcmp(name, "QueryGDBServer")) {
  160. write_packet(server, "");
  161. }
  162. if (!strcmp(name, "VAttachOrWaitSupported")) {
  163. write_packet(server, "");
  164. }
  165. if (!strcmp(name, "ProcessInfo")) {
  166. // Todo: process id parent-pid
  167. uint64_t pid;
  168. pid = wasm_debug_instance_get_pid(
  169. (WASMDebugInstance *)server->thread->debug_instance);
  170. char triple[256];
  171. // arch-vendor-os-env(format)
  172. mem2hex("wasm32-Ant-wasi-wasm", triple, strlen("wasm32-Ant-wasi-wasm"));
  173. sprintf(tmpbuf,
  174. "pid:%lx;parent-pid:%lx;vendor:Ant;ostype:wasi;arch:wasm32;"
  175. "triple:%s;endian:little;ptrsize:4;",
  176. pid, pid, triple);
  177. write_packet(server, tmpbuf);
  178. }
  179. if (!strcmp(name, "RegisterInfo0")) {
  180. sprintf(
  181. tmpbuf,
  182. "name:pc;alt-name:pc;bitsize:64;offset:0;encoding:uint;format:hex;"
  183. "set:General Purpose Registers;gcc:16;dwarf:16;generic:pc;");
  184. write_packet(server, tmpbuf);
  185. }
  186. else if (!strncmp(name, "RegisterInfo", strlen("RegisterInfo"))) {
  187. write_packet(server, "E45");
  188. }
  189. if (!strcmp(name, "StructuredDataPlugins")) {
  190. write_packet(server, "");
  191. }
  192. if (args && (!strcmp(name, "MemoryRegionInfo"))) {
  193. uint64_t addr = strtol(args, NULL, 16);
  194. WASMDebugMemoryInfo *mem_info = wasm_debug_instance_get_memregion(
  195. (WASMDebugInstance *)server->thread->debug_instance, addr);
  196. if (mem_info) {
  197. char name[256];
  198. mem2hex(mem_info->name, name, strlen(mem_info->name));
  199. sprintf(tmpbuf, "start:%lx;size:%lx;permissions:%s;name:%s;",
  200. (uint64)mem_info->start, mem_info->size,
  201. mem_info->permisson, name);
  202. write_packet(server, tmpbuf);
  203. wasm_debug_instance_destroy_memregion(
  204. (WASMDebugInstance *)server->thread->debug_instance, mem_info);
  205. }
  206. }
  207. if (!strcmp(name, "WasmData")) {
  208. }
  209. if (!strcmp(name, "WasmMem")) {
  210. }
  211. if (!strcmp(name, "Symbol")) {
  212. write_packet(server, "");
  213. }
  214. if (args && (!strcmp(name, "WasmCallStack"))) {
  215. uint64_t tid = strtol(args, NULL, 16);
  216. uint64_t buf[1024 / sizeof(uint64_t)];
  217. uint64_t count = wasm_debug_instance_get_call_stack_pcs(
  218. (WASMDebugInstance *)server->thread->debug_instance, tid, buf,
  219. 1024 / sizeof(uint64_t));
  220. if (count > 0) {
  221. mem2hex((char *)buf, tmpbuf, count * sizeof(uint64_t));
  222. write_packet(server, tmpbuf);
  223. }
  224. else
  225. write_packet(server, "");
  226. }
  227. if (args && (!strcmp(name, "WasmLocal"))) {
  228. porcess_wasm_local(server, args);
  229. }
  230. if (args && (!strcmp(name, "WasmGlobal"))) {
  231. porcess_wasm_global(server, args);
  232. }
  233. }
  234. static void
  235. send_thread_stop_status(WASMGDBServer *server, uint32_t status, uint64_t tid)
  236. {
  237. int tids_number, len = 0, i = 0;
  238. uint64_t tids[20];
  239. char pc_string[17];
  240. uint32_t gdb_status = status;
  241. if (status == 0) {
  242. sprintf(tmpbuf, "W%02x", status);
  243. write_packet(server, tmpbuf);
  244. return;
  245. }
  246. tids_number = wasm_debug_instance_get_tids(
  247. (WASMDebugInstance *)server->thread->debug_instance, tids, 20);
  248. uint64_t pc = wasm_debug_instance_get_pc(
  249. (WASMDebugInstance *)server->thread->debug_instance);
  250. if (status == WAMR_SIG_SINGSTEP) {
  251. gdb_status = WAMR_SIG_TRAP;
  252. }
  253. // TODO: how name a wasm thread?
  254. len +=
  255. sprintf(tmpbuf, "T%02xthread:%lx;name:%s;", gdb_status, tid, "nobody");
  256. if (tids_number > 0) {
  257. len += sprintf(tmpbuf + len, "threads:");
  258. while (i < tids_number) {
  259. if (i == tids_number - 1)
  260. len += sprintf(tmpbuf + len, "%lx;", tids[i]);
  261. else
  262. len += sprintf(tmpbuf + len, "%lx,", tids[i]);
  263. i++;
  264. }
  265. }
  266. mem2hex((void *)&pc, pc_string, 8);
  267. pc_string[8 * 2] = '\0';
  268. if (status == WAMR_SIG_TRAP) {
  269. len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
  270. pc_string, "breakpoint");
  271. }
  272. else if (status == WAMR_SIG_SINGSTEP) {
  273. len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
  274. pc_string, "trace");
  275. }
  276. else if (status > 0) {
  277. len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
  278. pc_string, "signal");
  279. }
  280. write_packet(server, tmpbuf);
  281. }
  282. void
  283. handle_v_packet(WASMGDBServer *server, char *payload)
  284. {
  285. const char *name;
  286. char *args;
  287. uint32_t status;
  288. args = strchr(payload, ';');
  289. if (args)
  290. *args++ = '\0';
  291. name = payload;
  292. LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
  293. if (!strcmp("Cont?", name))
  294. write_packet(server, "vCont;c;C;s;S;");
  295. if (!strcmp("Cont", name)) {
  296. if (args && args[0] == 's') {
  297. char *numstring = strchr(args, ':');
  298. if (numstring) {
  299. *numstring++ = '\0';
  300. uint64_t tid = strtol(numstring, NULL, 16);
  301. wasm_debug_instance_set_cur_thread(
  302. (WASMDebugInstance *)server->thread->debug_instance, tid);
  303. wasm_debug_instance_singlestep(
  304. (WASMDebugInstance *)server->thread->debug_instance, tid);
  305. tid = wasm_debug_instance_wait_thread(
  306. (WASMDebugInstance *)server->thread->debug_instance, tid,
  307. &status);
  308. send_thread_stop_status(server, status, tid);
  309. }
  310. }
  311. }
  312. }
  313. void
  314. handle_threadstop_request(WASMGDBServer *server, char *payload)
  315. {
  316. uint64_t tid = wasm_debug_instance_get_tid(
  317. (WASMDebugInstance *)server->thread->debug_instance);
  318. uint32_t status;
  319. tid = wasm_debug_instance_wait_thread(
  320. (WASMDebugInstance *)server->thread->debug_instance, tid, &status);
  321. send_thread_stop_status(server, status, tid);
  322. }
  323. void
  324. handle_set_current_thread(WASMGDBServer *server, char *payload)
  325. {
  326. LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload, payload);
  327. if ('g' == *payload++) {
  328. uint64_t tid;
  329. tid = strtol(payload, NULL, 16);
  330. if (tid > 0)
  331. wasm_debug_instance_set_cur_thread(
  332. (WASMDebugInstance *)server->thread->debug_instance, tid);
  333. }
  334. write_packet(server, "OK");
  335. }
  336. void
  337. handle_get_register(WASMGDBServer *server, char *payload)
  338. {
  339. int i = strtol(payload, NULL, 16);
  340. if (i != 0) {
  341. write_packet(server, "E01");
  342. return;
  343. }
  344. uint64_t regdata = wasm_debug_instance_get_pc(
  345. (WASMDebugInstance *)server->thread->debug_instance);
  346. mem2hex((void *)&regdata, tmpbuf, 8);
  347. tmpbuf[8 * 2] = '\0';
  348. write_packet(server, tmpbuf);
  349. }
  350. void
  351. handle_get_json_request(WASMGDBServer *server, char *payload)
  352. {
  353. char *args;
  354. args = strchr(payload, ':');
  355. if (args)
  356. *args++ = '\0';
  357. write_packet(server, "");
  358. }
  359. void
  360. handle_get_read_binary_memory(WASMGDBServer *server, char *payload)
  361. {
  362. write_packet(server, "");
  363. }
  364. void
  365. handle_get_read_memory(WASMGDBServer *server, char *payload)
  366. {
  367. size_t maddr, mlen;
  368. bool ret;
  369. sprintf(tmpbuf, "%s", "");
  370. if (sscanf(payload, "%zx,%zx", &maddr, &mlen) == 2) {
  371. if (mlen * 2 > MAX_PACKET_SIZE) {
  372. LOG_ERROR("Buffer overflow!");
  373. mlen = MAX_PACKET_SIZE / 2;
  374. }
  375. char *buff = wasm_runtime_malloc(mlen);
  376. if (buff) {
  377. ret = wasm_debug_instance_get_mem(
  378. (WASMDebugInstance *)server->thread->debug_instance, maddr,
  379. buff, &mlen);
  380. if (ret) {
  381. mem2hex(buff, tmpbuf, mlen);
  382. }
  383. wasm_runtime_free(buff);
  384. }
  385. }
  386. write_packet(server, tmpbuf);
  387. }
  388. void
  389. handle_get_write_memory(WASMGDBServer *server, char *payload)
  390. {
  391. size_t maddr, mlen, hex_len;
  392. int offset, act_len;
  393. char *buff;
  394. bool ret;
  395. sprintf(tmpbuf, "%s", "");
  396. if (sscanf(payload, "%zx,%zx:%n", &maddr, &mlen, &offset) == 2) {
  397. payload += offset;
  398. hex_len = strlen(payload);
  399. act_len = hex_len / 2 < mlen ? hex_len / 2 : mlen;
  400. buff = wasm_runtime_malloc(act_len);
  401. if (buff) {
  402. hex2mem(payload, buff, act_len);
  403. ret = wasm_debug_instance_set_mem(
  404. (WASMDebugInstance *)server->thread->debug_instance, maddr,
  405. buff, &mlen);
  406. if (ret) {
  407. sprintf(tmpbuf, "%s", "OK");
  408. }
  409. wasm_runtime_free(buff);
  410. }
  411. }
  412. write_packet(server, tmpbuf);
  413. }
  414. void
  415. handle_add_break(WASMGDBServer *server, char *payload)
  416. {
  417. size_t type, addr, length;
  418. if (sscanf(payload, "%zx,%zx,%zx", &type, &addr, &length) == 3) {
  419. if (type == eBreakpointSoftware) {
  420. bool ret = wasm_debug_instance_add_breakpoint(
  421. (WASMDebugInstance *)server->thread->debug_instance, addr,
  422. length);
  423. if (ret)
  424. write_packet(server, "OK");
  425. else
  426. write_packet(server, "E01");
  427. return;
  428. }
  429. }
  430. write_packet(server, "");
  431. }
  432. void
  433. handle_remove_break(WASMGDBServer *server, char *payload)
  434. {
  435. size_t type, addr, length;
  436. if (sscanf(payload, "%zx,%zx,%zx", &type, &addr, &length) == 3) {
  437. if (type == eBreakpointSoftware) {
  438. bool ret = wasm_debug_instance_remove_breakpoint(
  439. (WASMDebugInstance *)server->thread->debug_instance, addr,
  440. length);
  441. if (ret)
  442. write_packet(server, "OK");
  443. else
  444. write_packet(server, "E01");
  445. return;
  446. }
  447. }
  448. write_packet(server, "");
  449. }
  450. void
  451. handle_continue_request(WASMGDBServer *server, char *payload)
  452. {
  453. uint64_t tid;
  454. uint32_t status;
  455. wasm_debug_instance_continue(
  456. (WASMDebugInstance *)server->thread->debug_instance);
  457. tid = wasm_debug_instance_get_tid(
  458. (WASMDebugInstance *)server->thread->debug_instance);
  459. tid = wasm_debug_instance_wait_thread(
  460. (WASMDebugInstance *)server->thread->debug_instance, tid, &status);
  461. send_thread_stop_status(server, status, tid);
  462. }
  463. void
  464. handle_kill_request(WASMGDBServer *server, char *payload)
  465. {
  466. uint64_t tid;
  467. uint32_t status;
  468. wasm_debug_instance_kill(
  469. (WASMDebugInstance *)server->thread->debug_instance);
  470. tid = wasm_debug_instance_get_tid(
  471. (WASMDebugInstance *)server->thread->debug_instance);
  472. tid = wasm_debug_instance_wait_thread(
  473. (WASMDebugInstance *)server->thread->debug_instance, tid, &status);
  474. send_thread_stop_status(server, status, tid);
  475. }
  476. static void
  477. handle_malloc(WASMGDBServer *server, char *payload)
  478. {
  479. char *args;
  480. uint64_t size;
  481. int map_port = MMAP_PROT_NONE;
  482. uint64_t addr;
  483. sprintf(tmpbuf, "%s", "E03");
  484. args = strstr(payload, ",");
  485. if (args) {
  486. *args++ = '\0';
  487. }
  488. else {
  489. LOG_ERROR("Payload parse error during handle malloc");
  490. return;
  491. }
  492. size = strtol(payload, NULL, 16);
  493. if (size > 0) {
  494. while (*args) {
  495. if (*args == 'r') {
  496. map_port |= MMAP_PROT_READ;
  497. }
  498. if (*args == 'w') {
  499. map_port |= MMAP_PROT_WRITE;
  500. }
  501. if (*args == 'x') {
  502. map_port |= MMAP_PROT_EXEC;
  503. }
  504. args++;
  505. }
  506. addr = wasm_debug_instance_mmap(
  507. (WASMDebugInstance *)server->thread->debug_instance, size,
  508. map_port);
  509. if (addr) {
  510. sprintf(tmpbuf, "%lx", addr);
  511. }
  512. }
  513. write_packet(server, tmpbuf);
  514. }
  515. static void
  516. handle_free(WASMGDBServer *server, char *payload)
  517. {
  518. uint64_t addr;
  519. bool ret;
  520. sprintf(tmpbuf, "%s", "E03");
  521. addr = strtol(payload, NULL, 16);
  522. ret = wasm_debug_instance_ummap(
  523. (WASMDebugInstance *)server->thread->debug_instance, addr);
  524. if (ret) {
  525. sprintf(tmpbuf, "%s", "OK");
  526. }
  527. write_packet(server, tmpbuf);
  528. }
  529. void
  530. handle____request(WASMGDBServer *server, char *payload)
  531. {
  532. char *args;
  533. if (payload[0] == 'M') {
  534. args = payload + 1;
  535. handle_malloc(server, args);
  536. }
  537. if (payload[0] == 'm') {
  538. args = payload + 1;
  539. handle_free(server, args);
  540. }
  541. }