handler.c 16 KB

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