gdbserver.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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 (0 != os_socket_create(&listen_fd, 1)) {
  45. LOG_ERROR("wasm gdb server error: create socket failed");
  46. goto fail;
  47. }
  48. if (0 != os_socket_bind(listen_fd, host, port)) {
  49. LOG_ERROR("wasm gdb server error: socket bind failed");
  50. goto fail;
  51. }
  52. LOG_WARNING("Debug server listening on %s:%" PRIu32 "\n", host, *port);
  53. server->listen_fd = listen_fd;
  54. return server;
  55. fail:
  56. if (listen_fd >= 0) {
  57. os_socket_shutdown(listen_fd);
  58. os_socket_close(listen_fd);
  59. }
  60. if (server)
  61. wasm_runtime_free(server);
  62. return NULL;
  63. }
  64. bool
  65. wasm_gdbserver_listen(WASMGDBServer *server)
  66. {
  67. bh_socket_t sockt_fd = (bh_socket_t)-1;
  68. int32 ret;
  69. ret = os_socket_listen(server->listen_fd, 1);
  70. if (ret != 0) {
  71. LOG_ERROR("wasm gdb server error: socket listen failed");
  72. goto fail;
  73. }
  74. os_socket_accept(server->listen_fd, &sockt_fd, NULL, NULL);
  75. if (sockt_fd < 0) {
  76. LOG_ERROR("wasm gdb server error: socket accept failed");
  77. goto fail;
  78. }
  79. LOG_VERBOSE("accept gdb client");
  80. server->socket_fd = sockt_fd;
  81. server->noack = false;
  82. return true;
  83. fail:
  84. os_socket_shutdown(server->listen_fd);
  85. os_socket_close(server->listen_fd);
  86. return false;
  87. }
  88. void
  89. wasm_close_gdbserver(WASMGDBServer *server)
  90. {
  91. if (server->socket_fd > 0) {
  92. os_socket_shutdown(server->socket_fd);
  93. os_socket_close(server->socket_fd);
  94. }
  95. if (server->listen_fd > 0) {
  96. os_socket_shutdown(server->listen_fd);
  97. os_socket_close(server->listen_fd);
  98. }
  99. }
  100. static inline void
  101. handler_packet(WASMGDBServer *server, char request, char *payload)
  102. {
  103. if (packet_handler_table[(int)request].handler != NULL)
  104. packet_handler_table[(int)request].handler(server, payload);
  105. }
  106. /**
  107. * The packet layout is:
  108. * '$' + payload + '#' + checksum(2bytes)
  109. * ^
  110. * packetend_ptr
  111. */
  112. static void
  113. process_packet(WASMGDBServer *server)
  114. {
  115. uint8 *inbuf = server->pkt.buf;
  116. int32 inbuf_size = server->pkt.size;
  117. uint8 *packetend_ptr = (uint8 *)memchr(inbuf, '#', inbuf_size);
  118. int32 packet_size = (int32)(uintptr_t)(packetend_ptr - inbuf);
  119. char request = inbuf[1];
  120. char *payload = NULL;
  121. uint8 checksum = 0;
  122. if (packet_size == 1) {
  123. LOG_VERBOSE("receive empty request, ignore it\n");
  124. return;
  125. }
  126. bh_assert('$' == inbuf[0]);
  127. inbuf[packet_size] = '\0';
  128. for (int i = 1; i < packet_size; i++)
  129. checksum += inbuf[i];
  130. bh_assert(
  131. checksum
  132. == (hex(inbuf[packet_size + 1]) << 4 | hex(inbuf[packet_size + 2])));
  133. payload = (char *)&inbuf[2];
  134. LOG_VERBOSE("receive request:%c %s\n", request, payload);
  135. handler_packet(server, request, payload);
  136. inbuf_erase_head(server, packet_size + 3);
  137. }
  138. bool
  139. wasm_gdbserver_handle_packet(WASMGDBServer *server)
  140. {
  141. bool ret;
  142. ret = read_packet(server);
  143. if (ret)
  144. process_packet(server);
  145. return ret;
  146. }