gdbserver.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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 struct packet_handler_elem packet_handler_table[255] = {
  17. DEL_HANDLER('Q', handle_generay_set),
  18. DEL_HANDLER('q', handle_generay_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. };
  33. WASMGDBServer *
  34. wasm_create_gdbserver(const char *host, int32 *port)
  35. {
  36. bh_socket_t listen_fd = (bh_socket_t)-1;
  37. WASMGDBServer *server;
  38. bh_assert(port);
  39. if (!(server = wasm_runtime_malloc(sizeof(WASMGDBServer)))) {
  40. LOG_ERROR("wasm gdb server error: failed to allocate memory");
  41. return NULL;
  42. }
  43. memset(server, 0, sizeof(WASMGDBServer));
  44. if (!(server->receive_ctx =
  45. wasm_runtime_malloc(sizeof(rsp_recv_context_t)))) {
  46. LOG_ERROR("wasm gdb server error: failed to allocate memory");
  47. goto fail;
  48. }
  49. memset(server->receive_ctx, 0, sizeof(rsp_recv_context_t));
  50. if (0 != os_socket_create(&listen_fd, 1)) {
  51. LOG_ERROR("wasm gdb server error: create socket failed");
  52. goto fail;
  53. }
  54. if (0 != os_socket_bind(listen_fd, host, port)) {
  55. LOG_ERROR("wasm gdb server error: socket bind failed");
  56. goto fail;
  57. }
  58. LOG_WARNING("Debug server listening on %s:%" PRIu32 "\n", host, *port);
  59. server->listen_fd = listen_fd;
  60. return server;
  61. fail:
  62. if (listen_fd >= 0) {
  63. os_socket_shutdown(listen_fd);
  64. os_socket_close(listen_fd);
  65. }
  66. if (server->receive_ctx)
  67. wasm_runtime_free(server->receive_ctx);
  68. if (server)
  69. wasm_runtime_free(server);
  70. return NULL;
  71. }
  72. bool
  73. wasm_gdbserver_listen(WASMGDBServer *server)
  74. {
  75. bh_socket_t sockt_fd = (bh_socket_t)-1;
  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. os_socket_accept(server->listen_fd, &sockt_fd, NULL, NULL);
  83. if (sockt_fd < 0) {
  84. LOG_ERROR("wasm gdb server error: socket accept failed");
  85. goto fail;
  86. }
  87. LOG_VERBOSE("accept gdb client");
  88. server->socket_fd = sockt_fd;
  89. server->noack = false;
  90. return true;
  91. fail:
  92. os_socket_shutdown(server->listen_fd);
  93. os_socket_close(server->listen_fd);
  94. return false;
  95. }
  96. void
  97. wasm_close_gdbserver(WASMGDBServer *server)
  98. {
  99. if (server->receive_ctx) {
  100. wasm_runtime_free(server->receive_ctx);
  101. }
  102. if (server->socket_fd > 0) {
  103. os_socket_shutdown(server->socket_fd);
  104. os_socket_close(server->socket_fd);
  105. }
  106. if (server->listen_fd > 0) {
  107. os_socket_shutdown(server->listen_fd);
  108. os_socket_close(server->listen_fd);
  109. }
  110. }
  111. static inline void
  112. handle_packet(WASMGDBServer *server, char request, char *payload)
  113. {
  114. if (packet_handler_table[(int)request].handler != NULL)
  115. packet_handler_table[(int)request].handler(server, payload);
  116. }
  117. static void
  118. process_packet(WASMGDBServer *server)
  119. {
  120. uint8 *inbuf = (uint8 *)server->receive_ctx->receive_buffer;
  121. char request;
  122. char *payload = NULL;
  123. request = inbuf[0];
  124. if (request == '\0') {
  125. LOG_VERBOSE("ignore empty request");
  126. return;
  127. }
  128. payload = (char *)&inbuf[1];
  129. LOG_VERBOSE("receive request:%c %s\n", request, payload);
  130. handle_packet(server, request, payload);
  131. }
  132. static inline void
  133. push_byte(rsp_recv_context_t *ctx, unsigned char ch, bool checksum)
  134. {
  135. if (ctx->receive_index >= sizeof(ctx->receive_buffer)) {
  136. LOG_ERROR("RSP message buffer overflow");
  137. bh_assert(false);
  138. return;
  139. }
  140. ctx->receive_buffer[ctx->receive_index++] = ch;
  141. if (checksum) {
  142. ctx->check_sum += ch;
  143. }
  144. }
  145. /**
  146. * The packet layout is:
  147. * 1. Normal packet:
  148. * '$' + payload + '#' + checksum(2bytes)
  149. * ^
  150. * packetend
  151. * 2. Interrupt:
  152. * 0x03
  153. */
  154. /* return:
  155. * 0: incomplete message received
  156. * 1: complete message received
  157. * 2: interrupt message received
  158. */
  159. static int
  160. on_rsp_byte_arrive(unsigned char ch, rsp_recv_context_t *ctx)
  161. {
  162. if (ctx->phase == Phase_Idle) {
  163. ctx->receive_index = 0;
  164. ctx->check_sum = 0;
  165. if (ch == 0x03) {
  166. LOG_VERBOSE("Receive interrupt package");
  167. return 2;
  168. }
  169. else if (ch == '$') {
  170. ctx->phase = Phase_Payload;
  171. }
  172. return 0;
  173. }
  174. else if (ctx->phase == Phase_Payload) {
  175. if (ch == '#') {
  176. ctx->phase = Phase_Checksum;
  177. push_byte(ctx, ch, false);
  178. }
  179. else {
  180. push_byte(ctx, ch, true);
  181. }
  182. return 0;
  183. }
  184. else if (ctx->phase == Phase_Checksum) {
  185. ctx->size_in_phase++;
  186. push_byte(ctx, ch, false);
  187. if (ctx->size_in_phase == 2) {
  188. ctx->size_in_phase = 0;
  189. if ((hex(ctx->receive_buffer[ctx->receive_index - 2]) << 4
  190. | hex(ctx->receive_buffer[ctx->receive_index - 1]))
  191. != ctx->check_sum) {
  192. LOG_WARNING("RSP package checksum error, ignore it");
  193. ctx->phase = Phase_Idle;
  194. return 0;
  195. }
  196. else {
  197. /* Change # to \0 */
  198. ctx->receive_buffer[ctx->receive_index - 3] = '\0';
  199. ctx->phase = Phase_Idle;
  200. return 1;
  201. }
  202. }
  203. return 0;
  204. }
  205. /* Should never reach here */
  206. bh_assert(false);
  207. return 0;
  208. }
  209. bool
  210. wasm_gdbserver_handle_packet(WASMGDBServer *server)
  211. {
  212. int32 n;
  213. char buf[1024];
  214. if (os_socket_settimeout(server->socket_fd, 1000) != 0) {
  215. LOG_ERROR("Set socket recv timeout failed");
  216. return false;
  217. }
  218. n = os_socket_recv(server->socket_fd, buf, sizeof(buf));
  219. if (n == 0) {
  220. LOG_VERBOSE("Debugger disconnected");
  221. return false;
  222. }
  223. else if (n < 0) {
  224. #if defined(BH_PLATFORM_WINDOWS)
  225. if (WSAGetLastError() == WSAETIMEDOUT)
  226. #else
  227. if (errno == EAGAIN || errno == EWOULDBLOCK)
  228. #endif
  229. {
  230. /* No bytes arrived */
  231. return true;
  232. }
  233. else {
  234. LOG_ERROR("Socket receive error");
  235. return false;
  236. }
  237. }
  238. else {
  239. int32 i, ret;
  240. for (i = 0; i < n; i++) {
  241. ret = on_rsp_byte_arrive(buf[i], server->receive_ctx);
  242. if (ret == 1) {
  243. if (!server->noack)
  244. write_data_raw(server, (uint8 *)"+", 1);
  245. process_packet(server);
  246. }
  247. else if (ret == 2) {
  248. handle_interrupt(server);
  249. }
  250. }
  251. }
  252. return true;
  253. }