/* * Copyright (C) 2021 Ant Group. All rights reserved. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ #include "packets.h" #include #include "bh_log.h" #include "gdbserver.h" void pktbuf_insert(WASMGDBServer *gdbserver, const uint8_t *buf, ssize_t len) { WasmDebugPacket *pkt = &gdbserver->pkt; if ((unsigned long)(pkt->size + len) >= sizeof(pkt->buf)) { LOG_ERROR("Packet buffer overflow"); exit(-2); } memcpy(pkt->buf + pkt->size, buf, len); pkt->size += len; } void pktbuf_erase_head(WASMGDBServer *gdbserver, ssize_t index) { WasmDebugPacket *pkt = &gdbserver->pkt; memmove(pkt->buf, pkt->buf + index, pkt->size - index); pkt->size -= index; } void inbuf_erase_head(WASMGDBServer *gdbserver, ssize_t index) { pktbuf_erase_head(gdbserver, index); } void pktbuf_clear(WASMGDBServer *gdbserver) { WasmDebugPacket *pkt = &gdbserver->pkt; pkt->size = 0; } int read_data_once(WASMGDBServer *gdbserver) { ssize_t nread; uint8_t buf[4096]; nread = read(gdbserver->socket_fd, buf, sizeof(buf)); if (nread <= 0) { LOG_ERROR("Connection closed"); return -1; } pktbuf_insert(gdbserver, buf, nread); return nread; } void write_data_raw(WASMGDBServer *gdbserver, const uint8_t *data, ssize_t len) { ssize_t nwritten; nwritten = write(gdbserver->socket_fd, data, len); if (nwritten < 0) { LOG_ERROR("Write error\n"); exit(-2); } } void write_hex(WASMGDBServer *gdbserver, unsigned long hex) { char buf[32]; size_t len; len = snprintf(buf, sizeof(buf) - 1, "%02lx", hex); write_data_raw(gdbserver, (uint8_t *)buf, len); } void write_packet_bytes(WASMGDBServer *gdbserver, const uint8_t *data, size_t num_bytes) { uint8_t checksum; size_t i; write_data_raw(gdbserver, (uint8_t *)"$", 1); for (i = 0, checksum = 0; i < num_bytes; ++i) checksum += data[i]; write_data_raw(gdbserver, (uint8_t *)data, num_bytes); write_data_raw(gdbserver, (uint8_t *)"#", 1); write_hex(gdbserver, checksum); } void write_packet(WASMGDBServer *gdbserver, const char *data) { LOG_VERBOSE("send replay:%s", data); write_packet_bytes(gdbserver, (const uint8_t *)data, strlen(data)); } void write_binary_packet(WASMGDBServer *gdbserver, const char *pfx, const uint8_t *data, ssize_t num_bytes) { uint8_t *buf; ssize_t pfx_num_chars = strlen(pfx); ssize_t buf_num_bytes = 0, total_size; int i; total_size = 2 * num_bytes + pfx_num_chars; buf = wasm_runtime_malloc(total_size); if (!buf) { LOG_ERROR("Failed to allocate memory for binary packet"); return; } memset(buf, 0, total_size); memcpy(buf, pfx, pfx_num_chars); buf_num_bytes += pfx_num_chars; for (i = 0; i < num_bytes; ++i) { uint8_t b = data[i]; switch (b) { case '#': case '$': case '}': case '*': buf[buf_num_bytes++] = '}'; buf[buf_num_bytes++] = b ^ 0x20; break; default: buf[buf_num_bytes++] = b; break; } } write_packet_bytes(gdbserver, buf, buf_num_bytes); wasm_runtime_free(buf); } bool skip_to_packet_start(WASMGDBServer *gdbserver) { ssize_t start_index = -1, i; for (i = 0; i < gdbserver->pkt.size; ++i) { if (gdbserver->pkt.buf[i] == '$') { start_index = i; break; } } if (start_index < 0) { pktbuf_clear(gdbserver); return false; } pktbuf_erase_head(gdbserver, start_index); bh_assert(1 <= gdbserver->pkt.size); bh_assert('$' == gdbserver->pkt.buf[0]); return true; } bool read_packet(WASMGDBServer *gdbserver) { while (!skip_to_packet_start(gdbserver)) { if (read_data_once(gdbserver) < 0) return false; } if (!gdbserver->noack) write_data_raw(gdbserver, (uint8_t *)"+", 1); return true; }