gdbserver.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * Copyright (C) 2021 Ant Group. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "gdbserver.h"
  6. #include <arpa/inet.h>
  7. #include <fcntl.h>
  8. #include <netinet/in.h>
  9. #include <netinet/tcp.h>
  10. #include <signal.h>
  11. #include <stdbool.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <sys/poll.h>
  16. #include <sys/socket.h>
  17. #include <unistd.h>
  18. #include "bh_log.h"
  19. #include "handler.h"
  20. #include "packets.h"
  21. #include "utils.h"
  22. typedef void (*PacketHandler)(WASMGDBServer *server, char *payload);
  23. struct packet_handler_elem {
  24. char request;
  25. PacketHandler handler;
  26. };
  27. #define DEL_HANDLER(r, h) [r] = { .request = r, .handler = h }
  28. static struct packet_handler_elem packet_handler_table[255] = {
  29. DEL_HANDLER('Q', handle_generay_set),
  30. DEL_HANDLER('q', handle_generay_query),
  31. DEL_HANDLER('v', handle_v_packet),
  32. DEL_HANDLER('?', handle_threadstop_request),
  33. DEL_HANDLER('H', handle_set_current_thread),
  34. DEL_HANDLER('p', handle_get_register),
  35. DEL_HANDLER('j', handle_get_json_request),
  36. DEL_HANDLER('m', handle_get_read_memory),
  37. DEL_HANDLER('M', handle_get_write_memory),
  38. DEL_HANDLER('x', handle_get_read_binary_memory),
  39. DEL_HANDLER('Z', handle_add_break),
  40. DEL_HANDLER('z', handle_remove_break),
  41. DEL_HANDLER('c', handle_continue_request),
  42. DEL_HANDLER('k', handle_kill_request),
  43. DEL_HANDLER('_', handle____request),
  44. };
  45. WASMGDBServer *
  46. wasm_create_gdbserver(char *host, int *port)
  47. {
  48. int listen_fd = -1;
  49. const int one = 1;
  50. struct sockaddr_in addr;
  51. socklen_t socklen;
  52. int ret;
  53. WASMGDBServer *server;
  54. bh_assert(port);
  55. if (!(server = wasm_runtime_malloc(sizeof(WASMGDBServer)))) {
  56. LOG_ERROR("wasm gdb server error: failed to allocate memory");
  57. return NULL;
  58. }
  59. memset(server, 0, sizeof(WASMGDBServer));
  60. listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  61. if (listen_fd < 0) {
  62. LOG_ERROR("wasm gdb server error: socket() failed");
  63. goto fail;
  64. }
  65. ret = fcntl(listen_fd, F_SETFD, FD_CLOEXEC);
  66. if (ret < 0) {
  67. LOG_ERROR(
  68. "wasm gdb server error: fcntl() failed on setting FD_CLOEXEC");
  69. goto fail;
  70. }
  71. ret = setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
  72. if (ret < 0) {
  73. LOG_ERROR("wasm gdb server error: setsockopt() failed");
  74. goto fail;
  75. }
  76. addr.sin_family = AF_INET;
  77. addr.sin_addr.s_addr = inet_addr(host);
  78. addr.sin_port = htons(*port);
  79. ret = bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr));
  80. if (ret < 0) {
  81. LOG_ERROR("wasm gdb server error: bind() failed");
  82. goto fail;
  83. }
  84. socklen = sizeof(addr);
  85. if (getsockname(listen_fd, (void *)&addr, &socklen) == -1) {
  86. LOG_ERROR("%s", strerror(errno));
  87. goto fail;
  88. }
  89. LOG_WARNING("Debug server listening on %s:%d\n", host,
  90. ntohs(addr.sin_port));
  91. *port = ntohs(addr.sin_port);
  92. server->listen_fd = listen_fd;
  93. return server;
  94. fail:
  95. if (listen_fd >= 0) {
  96. shutdown(listen_fd, SHUT_RDWR);
  97. close(listen_fd);
  98. }
  99. if (server)
  100. wasm_runtime_free(server);
  101. return NULL;
  102. }
  103. bool
  104. wasm_gdbserver_listen(WASMGDBServer *server)
  105. {
  106. int ret;
  107. int sockt_fd = 0;
  108. ret = listen(server->listen_fd, 1);
  109. if (ret < 0) {
  110. LOG_ERROR("wasm gdb server error: listen() failed");
  111. goto fail;
  112. }
  113. sockt_fd = accept(server->listen_fd, NULL, NULL);
  114. if (sockt_fd < 0) {
  115. LOG_ERROR("wasm gdb server error: accept() failed");
  116. goto fail;
  117. }
  118. LOG_VERBOSE("accept gdb client");
  119. server->socket_fd = sockt_fd;
  120. server->noack = false;
  121. return true;
  122. fail:
  123. shutdown(server->listen_fd, SHUT_RDWR);
  124. close(server->listen_fd);
  125. return false;
  126. }
  127. void
  128. wasm_close_gdbserver(WASMGDBServer *server)
  129. {
  130. if (server->socket_fd > 0) {
  131. shutdown(server->socket_fd, SHUT_RDWR);
  132. close(server->socket_fd);
  133. }
  134. if (server->listen_fd > 0) {
  135. shutdown(server->listen_fd, SHUT_RDWR);
  136. close(server->listen_fd);
  137. }
  138. }
  139. static inline void
  140. handler_packet(WASMGDBServer *server, char request, char *payload)
  141. {
  142. if (packet_handler_table[(int)request].handler != NULL)
  143. packet_handler_table[(int)request].handler(server, payload);
  144. }
  145. /**
  146. * The packet layout is:
  147. * '$' + payload + '#' + checksum(2bytes)
  148. * ^
  149. * packetend_ptr
  150. */
  151. static void
  152. process_packet(WASMGDBServer *server)
  153. {
  154. uint8_t *inbuf = server->pkt.buf;
  155. int inbuf_size = server->pkt.size;
  156. uint8_t *packetend_ptr = (uint8_t *)memchr(inbuf, '#', inbuf_size);
  157. int packetend = packetend_ptr - inbuf;
  158. char request = inbuf[1];
  159. char *payload = NULL;
  160. uint8_t checksum = 0;
  161. if (packetend == 1) {
  162. LOG_VERBOSE("receive empty request, ignore it\n");
  163. return;
  164. }
  165. bh_assert('$' == inbuf[0]);
  166. inbuf[packetend] = '\0';
  167. for (int i = 1; i < packetend; i++)
  168. checksum += inbuf[i];
  169. bh_assert(checksum
  170. == (hex(inbuf[packetend + 1]) << 4 | hex(inbuf[packetend + 2])));
  171. payload = (char *)&inbuf[2];
  172. LOG_VERBOSE("receive request:%c %s\n", request, payload);
  173. handler_packet(server, request, payload);
  174. inbuf_erase_head(server, packetend + 3);
  175. }
  176. bool
  177. wasm_gdbserver_handle_packet(WASMGDBServer *server)
  178. {
  179. bool ret;
  180. ret = read_packet(server);
  181. if (ret)
  182. process_packet(server);
  183. return ret;
  184. }