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;",
  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, "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, strlen("wasm32-Ant-wasi-wasm"));
  170. sprintf(tmpbuf,
  171. "pid:%lx;parent-pid:%lx;vendor:Ant;ostype:wasi;arch:wasm32;"
  172. "triple:%s;endian:little;ptrsize:4;",
  173. pid, pid, triple);
  174. write_packet(server, tmpbuf);
  175. }
  176. if (!strcmp(name, "RegisterInfo0")) {
  177. sprintf(
  178. tmpbuf,
  179. "name:pc;alt-name:pc;bitsize:64;offset:0;encoding:uint;format:hex;"
  180. "set:General Purpose Registers;gcc:16;dwarf:16;generic:pc;");
  181. write_packet(server, tmpbuf);
  182. }
  183. else if (!strncmp(name, "RegisterInfo", strlen("RegisterInfo"))) {
  184. write_packet(server, "E45");
  185. }
  186. if (!strcmp(name, "StructuredDataPlugins")) {
  187. write_packet(server, "");
  188. }
  189. if (args && (!strcmp(name, "MemoryRegionInfo"))) {
  190. uint64_t addr = strtol(args, NULL, 16);
  191. WASMDebugMemoryInfo *mem_info = wasm_debug_instance_get_memregion(
  192. (WASMDebugInstance *)server->thread->debug_instance, addr);
  193. if (mem_info) {
  194. char name[256];
  195. mem2hex(mem_info->name, name, strlen(mem_info->name));
  196. sprintf(tmpbuf, "start:%lx;size:%lx;permissions:%s;name:%s;",
  197. (uint64)mem_info->start, mem_info->size,
  198. 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 +=
  252. sprintf(tmpbuf, "T%02xthread:%lx;name:%s;", gdb_status, tid, "nobody");
  253. if (tids_number > 0) {
  254. len += sprintf(tmpbuf + len, "threads:");
  255. while (i < tids_number) {
  256. if (i == tids_number - 1)
  257. len += sprintf(tmpbuf + len, "%lx;", tids[i]);
  258. else
  259. len += sprintf(tmpbuf + len, "%lx,", tids[i]);
  260. i++;
  261. }
  262. }
  263. mem2hex((void *)&pc, pc_string, 8);
  264. pc_string[8 * 2] = '\0';
  265. if (status == WAMR_SIG_TRAP) {
  266. len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
  267. pc_string, "breakpoint");
  268. }
  269. else if (status == WAMR_SIG_SINGSTEP) {
  270. len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
  271. pc_string, "trace");
  272. }
  273. else if (status > 0) {
  274. len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
  275. pc_string, "signal");
  276. }
  277. write_packet(server, tmpbuf);
  278. }
  279. void
  280. handle_v_packet(WASMGDBServer *server, char *payload)
  281. {
  282. const char *name;
  283. char *args;
  284. uint32_t status;
  285. args = strchr(payload, ';');
  286. if (args)
  287. *args++ = '\0';
  288. name = payload;
  289. LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
  290. if (!strcmp("Cont?", name))
  291. write_packet(server, "vCont;c;C;s;S;");
  292. if (!strcmp("Cont", name)) {
  293. if (args && args[0] == 's') {
  294. char *numstring = strchr(args, ':');
  295. if (numstring) {
  296. *numstring++ = '\0';
  297. uint64_t tid = strtol(numstring, NULL, 16);
  298. wasm_debug_instance_set_cur_thread(
  299. (WASMDebugInstance *)server->thread->debug_instance, tid);
  300. wasm_debug_instance_singlestep(
  301. (WASMDebugInstance *)server->thread->debug_instance, tid);
  302. tid = wasm_debug_instance_wait_thread(
  303. (WASMDebugInstance *)server->thread->debug_instance, tid,
  304. &status);
  305. send_thread_stop_status(server, status, tid);
  306. }
  307. }
  308. }
  309. }
  310. void
  311. handle_threadstop_request(WASMGDBServer *server, char *payload)
  312. {
  313. uint64_t tid = wasm_debug_instance_get_tid(
  314. (WASMDebugInstance *)server->thread->debug_instance);
  315. uint32_t status;
  316. tid = wasm_debug_instance_wait_thread(
  317. (WASMDebugInstance *)server->thread->debug_instance, tid, &status);
  318. send_thread_stop_status(server, status, tid);
  319. }
  320. void
  321. handle_set_current_thread(WASMGDBServer *server, char *payload)
  322. {
  323. LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload, payload);
  324. if ('g' == *payload++) {
  325. uint64_t tid;
  326. tid = strtol(payload, NULL, 16);
  327. if (tid > 0)
  328. wasm_debug_instance_set_cur_thread(
  329. (WASMDebugInstance *)server->thread->debug_instance, tid);
  330. }
  331. write_packet(server, "OK");
  332. }
  333. void
  334. handle_get_register(WASMGDBServer *server, char *payload)
  335. {
  336. int i = strtol(payload, NULL, 16);
  337. if (i != 0) {
  338. write_packet(server, "E01");
  339. return;
  340. }
  341. uint64_t regdata = wasm_debug_instance_get_pc(
  342. (WASMDebugInstance *)server->thread->debug_instance);
  343. mem2hex((void *)&regdata, tmpbuf, 8);
  344. tmpbuf[8 * 2] = '\0';
  345. write_packet(server, tmpbuf);
  346. }
  347. void
  348. handle_get_json_request(WASMGDBServer *server, char *payload)
  349. {
  350. char *args;
  351. args = strchr(payload, ':');
  352. if (args)
  353. *args++ = '\0';
  354. write_packet(server, "");
  355. }
  356. void
  357. handle_get_read_binary_memory(WASMGDBServer *server, char *payload)
  358. {
  359. write_packet(server, "");
  360. }
  361. void
  362. handle_get_read_memory(WASMGDBServer *server, char *payload)
  363. {
  364. size_t maddr, mlen;
  365. bool ret;
  366. sprintf(tmpbuf, "%s", "");
  367. if (sscanf(payload, "%zx,%zx", &maddr, &mlen) == 2) {
  368. if (mlen * 2 > MAX_PACKET_SIZE) {
  369. LOG_ERROR("Buffer overflow!");
  370. mlen = MAX_PACKET_SIZE / 2;
  371. }
  372. char *buff = wasm_runtime_malloc(mlen);
  373. if (buff) {
  374. ret = wasm_debug_instance_get_mem(
  375. (WASMDebugInstance *)server->thread->debug_instance, maddr,
  376. buff, &mlen);
  377. if (ret) {
  378. mem2hex(buff, tmpbuf, mlen);
  379. }
  380. wasm_runtime_free(buff);
  381. }
  382. }
  383. write_packet(server, tmpbuf);
  384. }
  385. void
  386. handle_get_write_memory(WASMGDBServer *server, char *payload)
  387. {
  388. size_t maddr, mlen, hex_len;
  389. int offset, act_len;
  390. char *buff;
  391. bool ret;
  392. sprintf(tmpbuf, "%s", "");
  393. if (sscanf(payload, "%zx,%zx:%n", &maddr, &mlen, &offset) == 2) {
  394. payload += offset;
  395. hex_len = strlen(payload);
  396. act_len = hex_len / 2 < mlen ? hex_len / 2 : mlen;
  397. buff = wasm_runtime_malloc(act_len);
  398. if (buff) {
  399. hex2mem(payload, buff, act_len);
  400. ret = wasm_debug_instance_set_mem(
  401. (WASMDebugInstance *)server->thread->debug_instance, maddr,
  402. buff, &mlen);
  403. if (ret) {
  404. sprintf(tmpbuf, "%s", "OK");
  405. }
  406. wasm_runtime_free(buff);
  407. }
  408. }
  409. write_packet(server, tmpbuf);
  410. }
  411. void
  412. handle_add_break(WASMGDBServer *server, char *payload)
  413. {
  414. size_t type, addr, length;
  415. if (sscanf(payload, "%zx,%zx,%zx", &type, &addr, &length) == 3) {
  416. if (type == eBreakpointSoftware) {
  417. bool ret = wasm_debug_instance_add_breakpoint(
  418. (WASMDebugInstance *)server->thread->debug_instance, addr,
  419. length);
  420. if (ret)
  421. write_packet(server, "OK");
  422. else
  423. write_packet(server, "E01");
  424. return;
  425. }
  426. }
  427. write_packet(server, "");
  428. }
  429. void
  430. handle_remove_break(WASMGDBServer *server, char *payload)
  431. {
  432. size_t type, addr, length;
  433. if (sscanf(payload, "%zx,%zx,%zx", &type, &addr, &length) == 3) {
  434. if (type == eBreakpointSoftware) {
  435. bool ret = wasm_debug_instance_remove_breakpoint(
  436. (WASMDebugInstance *)server->thread->debug_instance, addr,
  437. length);
  438. if (ret)
  439. write_packet(server, "OK");
  440. else
  441. write_packet(server, "E01");
  442. return;
  443. }
  444. }
  445. write_packet(server, "");
  446. }
  447. void
  448. handle_continue_request(WASMGDBServer *server, char *payload)
  449. {
  450. uint64_t tid;
  451. uint32_t status;
  452. wasm_debug_instance_continue(
  453. (WASMDebugInstance *)server->thread->debug_instance);
  454. tid = wasm_debug_instance_get_tid(
  455. (WASMDebugInstance *)server->thread->debug_instance);
  456. tid = wasm_debug_instance_wait_thread(
  457. (WASMDebugInstance *)server->thread->debug_instance, tid, &status);
  458. send_thread_stop_status(server, status, tid);
  459. }
  460. void
  461. handle_kill_request(WASMGDBServer *server, char *payload)
  462. {
  463. uint64_t tid;
  464. uint32_t status;
  465. wasm_debug_instance_kill(
  466. (WASMDebugInstance *)server->thread->debug_instance);
  467. tid = wasm_debug_instance_get_tid(
  468. (WASMDebugInstance *)server->thread->debug_instance);
  469. tid = wasm_debug_instance_wait_thread(
  470. (WASMDebugInstance *)server->thread->debug_instance, tid, &status);
  471. send_thread_stop_status(server, status, tid);
  472. }
  473. static void
  474. handle_malloc(WASMGDBServer *server, char *payload)
  475. {
  476. char *args;
  477. uint64_t size;
  478. int map_port = MMAP_PROT_NONE;
  479. uint64_t addr;
  480. sprintf(tmpbuf, "%s", "E03");
  481. args = strstr(payload, ",");
  482. if (args) {
  483. *args++ = '\0';
  484. }
  485. else {
  486. LOG_ERROR("Payload parse error during handle malloc");
  487. return;
  488. }
  489. size = strtol(payload, NULL, 16);
  490. if (size > 0) {
  491. while (*args) {
  492. if (*args == 'r') {
  493. map_port |= MMAP_PROT_READ;
  494. }
  495. if (*args == 'w') {
  496. map_port |= MMAP_PROT_WRITE;
  497. }
  498. if (*args == 'x') {
  499. map_port |= MMAP_PROT_EXEC;
  500. }
  501. args++;
  502. }
  503. addr = wasm_debug_instance_mmap(
  504. (WASMDebugInstance *)server->thread->debug_instance, size,
  505. map_port);
  506. if (addr) {
  507. sprintf(tmpbuf, "%lx", addr);
  508. }
  509. }
  510. write_packet(server, tmpbuf);
  511. }
  512. static void
  513. handle_free(WASMGDBServer *server, char *payload)
  514. {
  515. uint64_t addr;
  516. bool ret;
  517. sprintf(tmpbuf, "%s", "E03");
  518. addr = strtol(payload, NULL, 16);
  519. ret = wasm_debug_instance_ummap(
  520. (WASMDebugInstance *)server->thread->debug_instance, addr);
  521. if (ret) {
  522. sprintf(tmpbuf, "%s", "OK");
  523. }
  524. write_packet(server, tmpbuf);
  525. }
  526. void
  527. handle____request(WASMGDBServer *server, char *payload)
  528. {
  529. char *args;
  530. if (payload[0] == 'M') {
  531. args = payload + 1;
  532. handle_malloc(server, args);
  533. }
  534. if (payload[0] == 'm') {
  535. args = payload + 1;
  536. handle_free(server, args);
  537. }
  538. }