gdbserver.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. * Copyright (C) 2021 Ant Group. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "bh_platform.h"
  6. #include "gdbserver.h"
  7. #include "handler.h"
  8. #include "packets.h"
  9. #include "utils.h"
  10. typedef void (*PacketHandler)(WASMGDBServer *server, char *payload);
  11. struct packet_handler_elem {
  12. char request;
  13. PacketHandler handler;
  14. };
  15. #define DEL_HANDLER(r, h) [r] = { .request = r, .handler = h }
  16. static const struct packet_handler_elem packet_handler_table[255] = {
  17. DEL_HANDLER('Q', handle_general_set),
  18. DEL_HANDLER('q', handle_general_query),
  19. DEL_HANDLER('v', handle_v_packet),
  20. DEL_HANDLER('?', handle_threadstop_request),
  21. DEL_HANDLER('H', handle_set_current_thread),
  22. DEL_HANDLER('p', handle_get_register),
  23. DEL_HANDLER('j', handle_get_json_request),
  24. DEL_HANDLER('m', handle_get_read_memory),
  25. DEL_HANDLER('M', handle_get_write_memory),
  26. DEL_HANDLER('x', handle_get_read_binary_memory),
  27. DEL_HANDLER('Z', handle_add_break),
  28. DEL_HANDLER('z', handle_remove_break),
  29. DEL_HANDLER('c', handle_continue_request),
  30. DEL_HANDLER('k', handle_kill_request),
  31. DEL_HANDLER('_', handle____request),
  32. DEL_HANDLER('D', handle_detach_request),
  33. };
  34. WASMGDBServer *
  35. wasm_create_gdbserver(const char *host, int *port)
  36. {
  37. bh_socket_t listen_fd = (bh_socket_t)-1;
  38. WASMGDBServer *server;
  39. bh_assert(port);
  40. if (!(server = wasm_runtime_malloc(sizeof(WASMGDBServer)))) {
  41. LOG_ERROR("wasm gdb server error: failed to allocate memory");
  42. return NULL;
  43. }
  44. memset(server, 0, sizeof(WASMGDBServer));
  45. if (!(server->receive_ctx =
  46. wasm_runtime_malloc(sizeof(rsp_recv_context_t)))) {
  47. LOG_ERROR("wasm gdb server error: failed to allocate memory");
  48. goto fail;
  49. }
  50. memset(server->receive_ctx, 0, sizeof(rsp_recv_context_t));
  51. if (0 != os_socket_create(&listen_fd, true, true)) {
  52. LOG_ERROR("wasm gdb server error: create socket failed");
  53. goto fail;
  54. }
  55. if (0 != os_socket_bind(listen_fd, host, port)) {
  56. LOG_ERROR("wasm gdb server error: socket bind failed");
  57. goto fail;
  58. }
  59. LOG_WARNING("Debug server listening on %s:%" PRIu32 "\n", host, *port);
  60. server->listen_fd = listen_fd;
  61. return server;
  62. fail:
  63. if (listen_fd >= 0) {
  64. os_socket_shutdown(listen_fd);
  65. os_socket_close(listen_fd);
  66. }
  67. if (server->receive_ctx)
  68. wasm_runtime_free(server->receive_ctx);
  69. if (server)
  70. wasm_runtime_free(server);
  71. return NULL;
  72. }
  73. bool
  74. wasm_gdbserver_listen(WASMGDBServer *server)
  75. {
  76. int32 ret;
  77. ret = os_socket_listen(server->listen_fd, 1);
  78. if (ret != 0) {
  79. LOG_ERROR("wasm gdb server error: socket listen failed");
  80. goto fail;
  81. }
  82. LOG_VERBOSE("listen for gdb client");
  83. return true;
  84. fail:
  85. os_socket_shutdown(server->listen_fd);
  86. os_socket_close(server->listen_fd);
  87. return false;
  88. }
  89. bool
  90. wasm_gdbserver_accept(WASMGDBServer *server)
  91. {
  92. bh_socket_t sockt_fd = (bh_socket_t)-1;
  93. LOG_VERBOSE("waiting for gdb client to connect...");
  94. os_socket_accept(server->listen_fd, &sockt_fd, NULL, NULL);
  95. if (sockt_fd < 0) {
  96. LOG_ERROR("wasm gdb server error: socket accept failed");
  97. goto fail;
  98. }
  99. LOG_VERBOSE("accept gdb client");
  100. server->socket_fd = sockt_fd;
  101. server->noack = false;
  102. return true;
  103. fail:
  104. os_socket_shutdown(server->listen_fd);
  105. os_socket_close(server->listen_fd);
  106. return false;
  107. }
  108. void
  109. wasm_gdbserver_detach(WASMGDBServer *server)
  110. {
  111. if (server->socket_fd > 0) {
  112. os_socket_shutdown(server->socket_fd);
  113. os_socket_close(server->socket_fd);
  114. }
  115. }
  116. void
  117. wasm_close_gdbserver(WASMGDBServer *server)
  118. {
  119. if (server->receive_ctx) {
  120. wasm_runtime_free(server->receive_ctx);
  121. }
  122. if (server->socket_fd > 0) {
  123. os_socket_shutdown(server->socket_fd);
  124. os_socket_close(server->socket_fd);
  125. }
  126. if (server->listen_fd > 0) {
  127. os_socket_shutdown(server->listen_fd);
  128. os_socket_close(server->listen_fd);
  129. }
  130. }
  131. static inline void
  132. handle_packet(WASMGDBServer *server, char request, char *payload)
  133. {
  134. if (packet_handler_table[(int)request].handler != NULL)
  135. packet_handler_table[(int)request].handler(server, payload);
  136. }
  137. static void
  138. process_packet(WASMGDBServer *server)
  139. {
  140. uint8 *inbuf = (uint8 *)server->receive_ctx->receive_buffer;
  141. char request;
  142. char *payload = NULL;
  143. request = inbuf[0];
  144. if (request == '\0') {
  145. LOG_VERBOSE("ignore empty request");
  146. return;
  147. }
  148. payload = (char *)&inbuf[1];
  149. LOG_VERBOSE("receive request:%c %s\n", request, payload);
  150. handle_packet(server, request, payload);
  151. }
  152. static inline void
  153. push_byte(rsp_recv_context_t *ctx, unsigned char ch, bool checksum)
  154. {
  155. if (ctx->receive_index >= sizeof(ctx->receive_buffer)) {
  156. LOG_ERROR("RSP message buffer overflow");
  157. bh_assert(false);
  158. return;
  159. }
  160. ctx->receive_buffer[ctx->receive_index++] = ch;
  161. if (checksum) {
  162. ctx->check_sum += ch;
  163. }
  164. }
  165. /**
  166. * The packet layout is:
  167. * 1. Normal packet:
  168. * '$' + payload + '#' + checksum(2bytes)
  169. * ^
  170. * packetend
  171. * 2. Interrupt:
  172. * 0x03
  173. */
  174. /* return:
  175. * 0: incomplete message received
  176. * 1: complete message received
  177. * 2: interrupt message received
  178. */
  179. static int
  180. on_rsp_byte_arrive(unsigned char ch, rsp_recv_context_t *ctx)
  181. {
  182. if (ctx->phase == Phase_Idle) {
  183. ctx->receive_index = 0;
  184. ctx->check_sum = 0;
  185. if (ch == 0x03) {
  186. LOG_VERBOSE("Receive interrupt package");
  187. return 2;
  188. }
  189. else if (ch == '$') {
  190. ctx->phase = Phase_Payload;
  191. }
  192. return 0;
  193. }
  194. else if (ctx->phase == Phase_Payload) {
  195. if (ch == '#') {
  196. ctx->phase = Phase_Checksum;
  197. push_byte(ctx, ch, false);
  198. }
  199. else {
  200. push_byte(ctx, ch, true);
  201. }
  202. return 0;
  203. }
  204. else if (ctx->phase == Phase_Checksum) {
  205. ctx->size_in_phase++;
  206. push_byte(ctx, ch, false);
  207. if (ctx->size_in_phase == 2) {
  208. ctx->size_in_phase = 0;
  209. bh_assert(ctx->receive_index >= 3);
  210. if ((hex(ctx->receive_buffer[ctx->receive_index - 2]) << 4
  211. | hex(ctx->receive_buffer[ctx->receive_index - 1]))
  212. != ctx->check_sum) {
  213. LOG_WARNING("RSP package checksum error, ignore it");
  214. ctx->phase = Phase_Idle;
  215. return 0;
  216. }
  217. else {
  218. /* Change # to \0 */
  219. ctx->receive_buffer[ctx->receive_index - 3] = '\0';
  220. ctx->phase = Phase_Idle;
  221. return 1;
  222. }
  223. }
  224. return 0;
  225. }
  226. /* Should never reach here */
  227. bh_assert(false);
  228. return 0;
  229. }
  230. bool
  231. wasm_gdbserver_handle_packet(WASMGDBServer *server)
  232. {
  233. int32 n;
  234. char buf[1024];
  235. if (os_socket_settimeout(server->socket_fd, 1000) != 0) {
  236. LOG_ERROR("Set socket recv timeout failed");
  237. return false;
  238. }
  239. n = os_socket_recv(server->socket_fd, buf, sizeof(buf));
  240. if (n == 0) {
  241. handle_detach_request(server, NULL);
  242. LOG_VERBOSE("Debugger disconnected, waiting for debugger reconnection");
  243. return true;
  244. }
  245. else if (n < 0) {
  246. #if defined(BH_PLATFORM_WINDOWS)
  247. if (WSAGetLastError() == WSAETIMEDOUT)
  248. #else
  249. if (errno == EAGAIN || errno == EWOULDBLOCK)
  250. #endif
  251. {
  252. /* No bytes arrived */
  253. return true;
  254. }
  255. else {
  256. LOG_ERROR("Socket receive error");
  257. return false;
  258. }
  259. }
  260. else {
  261. int32 i, ret;
  262. for (i = 0; i < n; i++) {
  263. ret = on_rsp_byte_arrive(buf[i], server->receive_ctx);
  264. if (ret == 1) {
  265. if (!server->noack)
  266. write_data_raw(server, (uint8 *)"+", 1);
  267. process_packet(server);
  268. }
  269. else if (ret == 2) {
  270. handle_interrupt(server);
  271. }
  272. }
  273. }
  274. return true;
  275. }