Enable source debugging feature for windows platform (#910)

- use platform independent data types in debug-engine library
- add os_socket APIs and provide windows and posix implementation
- avoid using platform related header files in non-platform layer
- use format specifiers macros for sprintf and sscanf
- change thread handle type from uint64 to korp_tid
- add lock when sending socket packet to avoid thread racing
This commit is contained in:
Xu Jun 2021-12-22 19:52:07 +08:00 committed by GitHub
parent af251e45ca
commit ccb2de35d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 851 additions and 316 deletions

View File

@ -4,9 +4,8 @@
*/
#include "debug_engine.h"
#include "bh_log.h"
#include "gdbserver.h"
#include "handler.h"
#include "bh_platform.h"
#include "wasm_interp.h"
#include "wasm_opcode.h"
@ -18,8 +17,8 @@ typedef struct WASMDebugEngine {
struct WASMDebugEngine *next;
WASMDebugControlThread *control_thread;
char ip_addr[128];
int platform_port;
int process_base_port;
int32 platform_port;
int32 process_base_port;
bh_list debug_instance_list;
korp_mutex instance_list_lock;
bool active;
@ -66,7 +65,8 @@ control_thread_routine(void *arg)
control_thread->debug_engine = g_debug_engine;
control_thread->debug_instance = debug_inst;
strcpy(control_thread->ip_addr, g_debug_engine->ip_addr);
bh_strcpy_s(control_thread->ip_addr, sizeof(control_thread->ip_addr),
g_debug_engine->ip_addr);
control_thread->port =
(g_debug_engine->process_base_port == 0)
? 0
@ -171,6 +171,7 @@ static void
wasm_debug_control_thread_destroy(WASMDebugInstance *debug_instance)
{
WASMDebugControlThread *control_thread = debug_instance->control_thread;
LOG_VERBOSE("stopping control thread of debug object [%p]\n",
debug_instance);
control_thread->status = STOPPED;
@ -222,6 +223,7 @@ void
wasm_debug_engine_destroy()
{
if (g_debug_engine) {
wasm_debug_handler_deinit();
os_mutex_destroy(&g_debug_engine->instance_list_lock);
wasm_runtime_free(g_debug_engine);
g_debug_engine = NULL;
@ -229,10 +231,15 @@ wasm_debug_engine_destroy()
}
bool
wasm_debug_engine_init(char *ip_addr, int platform_port, int process_port)
wasm_debug_engine_init(char *ip_addr, int32 platform_port, int32 process_port)
{
if (g_debug_engine == NULL)
if (wasm_debug_handler_init() != 0) {
return false;
}
if (g_debug_engine == NULL) {
g_debug_engine = wasm_debug_engine_create();
}
if (g_debug_engine) {
process_port -= 1;
@ -241,11 +248,16 @@ wasm_debug_engine_init(char *ip_addr, int platform_port, int process_port)
g_debug_engine->process_base_port =
(process_port > 0) ? process_port : 0;
if (ip_addr)
sprintf(g_debug_engine->ip_addr, "%s", ip_addr);
snprintf(g_debug_engine->ip_addr, sizeof(g_debug_engine->ip_addr),
"%s", ip_addr);
else
sprintf(g_debug_engine->ip_addr, "%s", "127.0.0.1");
snprintf(g_debug_engine->ip_addr, sizeof(g_debug_engine->ip_addr),
"%s", "127.0.0.1");
g_debug_engine->active = true;
}
else {
wasm_debug_handler_deinit();
}
return g_debug_engine != NULL ? true : false;
}
@ -385,7 +397,7 @@ wasm_debug_instance_get_current_env(WASMDebugInstance *instance)
#if WASM_ENABLE_LIBC_WASI != 0
bool
wasm_debug_instance_get_current_object_name(WASMDebugInstance *instance,
char name_buffer[], int len)
char name_buffer[], uint32 len)
{
WASMExecEnv *exec_env;
WASIArguments *wasi_args;
@ -402,12 +414,13 @@ wasm_debug_instance_get_current_object_name(WASMDebugInstance *instance,
wasi_args = &module_inst->module->wasi_args;
if (wasi_args && wasi_args->argc > 0) {
char *argv_name = wasi_args->argv[0];
int name_len = strlen(argv_name);
uint32 name_len = (uint32)strlen(argv_name);
printf("the module name is %s\n", argv_name);
if (len - 1 >= name_len)
strcpy(name_buffer, argv_name);
bh_strcpy_s(name_buffer, len, argv_name);
else
strcpy(name_buffer, argv_name + (name_len + 1 - len));
bh_strcpy_s(name_buffer, len, argv_name + (name_len + 1 - len));
return true;
}
return false;
@ -423,21 +436,21 @@ wasm_debug_instance_get_pid(WASMDebugInstance *instance)
return (uint64)0;
}
uint64
korp_tid
wasm_debug_instance_get_tid(WASMDebugInstance *instance)
{
if (instance != NULL) {
return (uint64)instance->current_tid;
return instance->current_tid;
}
return (uint64)0;
return (korp_tid)(uintptr_t)0;
}
int
wasm_debug_instance_get_tids(WASMDebugInstance *instance, uint64 tids[],
int len)
uint32
wasm_debug_instance_get_tids(WASMDebugInstance *instance, korp_tid tids[],
uint32 len)
{
WASMExecEnv *exec_env;
int i = 0, threads_num = 0;
uint32 i = 0, threads_num = 0;
if (!instance)
return 0;
@ -471,8 +484,8 @@ get_stopped_thread(WASMCluster *cluster)
return NULL;
}
uint64
wasm_debug_instance_wait_thread(WASMDebugInstance *instance, uint64 tid,
korp_tid
wasm_debug_instance_wait_thread(WASMDebugInstance *instance, korp_tid tid,
uint32 *status)
{
WASMExecEnv *exec_env = NULL;
@ -491,19 +504,19 @@ wasm_debug_instance_wait_thread(WASMDebugInstance *instance, uint64 tid,
}
instance->current_tid = exec_env->handle;
*status = exec_env->current_status->signal_flag;
*status = (uint32)exec_env->current_status->signal_flag;
return exec_env->handle;
}
uint32
wasm_debug_instance_get_thread_status(WASMDebugInstance *instance, uint64 tid)
wasm_debug_instance_get_thread_status(WASMDebugInstance *instance, korp_tid tid)
{
WASMExecEnv *exec_env = NULL;
exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
while (exec_env) {
if (exec_env->handle == tid) {
return exec_env->current_status->signal_flag;
return (uint32)exec_env->current_status->signal_flag;
}
exec_env = bh_list_elem_next(exec_env);
}
@ -512,7 +525,7 @@ wasm_debug_instance_get_thread_status(WASMDebugInstance *instance, uint64 tid)
}
void
wasm_debug_instance_set_cur_thread(WASMDebugInstance *instance, uint64 tid)
wasm_debug_instance_set_cur_thread(WASMDebugInstance *instance, korp_tid tid)
{
instance->current_tid = tid;
}
@ -586,8 +599,10 @@ wasm_debug_instance_get_memregion(WASMDebugInstance *instance, uint64 addr)
if (WASM_ADDR_OFFSET(addr) < module_inst->module->load_size) {
mem_info->start = WASM_ADDR(WasmObj, instance->id, 0);
mem_info->size = module_inst->module->load_size;
sprintf(mem_info->name, "%s", "module");
sprintf(mem_info->permisson, "%s", "rx");
snprintf(mem_info->name, sizeof(mem_info->name), "%s",
"module");
snprintf(mem_info->permisson, sizeof(mem_info->permisson), "%s",
"rx");
}
break;
case WasmMemory:
@ -601,8 +616,10 @@ wasm_debug_instance_get_memregion(WASMDebugInstance *instance, uint64 addr)
if (WASM_ADDR_OFFSET(addr) < linear_mem_size) {
mem_info->start = WASM_ADDR(WasmMemory, instance->id, 0);
mem_info->size = linear_mem_size;
sprintf(mem_info->name, "%s", "memory");
sprintf(mem_info->permisson, "%s", "rw");
snprintf(mem_info->name, sizeof(mem_info->name), "%s",
"memory");
snprintf(mem_info->permisson, sizeof(mem_info->permisson), "%s",
"rw");
}
break;
}
@ -626,6 +643,8 @@ wasm_debug_instance_get_obj_mem(WASMDebugInstance *instance, uint64 offset,
{
WASMExecEnv *exec_env;
WASMModuleInstance *module_inst;
WASMDebugBreakPoint *breakpoint;
WASMFastOPCodeNode *fast_opcode;
if (!instance)
return false;
@ -643,11 +662,10 @@ wasm_debug_instance_get_obj_mem(WASMDebugInstance *instance, uint64 offset,
: 0;
}
bh_memcpy_s(buf, *size, module_inst->module->load_addr + offset, *size);
WASMDebugBreakPoint *breakpoint =
bh_list_first_elem(&instance->break_point_list);
bh_memcpy_s(buf, (uint32)*size, module_inst->module->load_addr + offset,
(uint32)*size);
breakpoint = bh_list_first_elem(&instance->break_point_list);
while (breakpoint) {
if (offset <= breakpoint->addr && breakpoint->addr < offset + *size) {
bh_memcpy_s(buf + (breakpoint->addr - offset), sizeof(break_instr),
@ -656,8 +674,7 @@ wasm_debug_instance_get_obj_mem(WASMDebugInstance *instance, uint64 offset,
breakpoint = bh_list_elem_next(breakpoint);
}
WASMFastOPCodeNode *fast_opcode =
bh_list_first_elem(&module_inst->module->fast_opcode_list);
fast_opcode = bh_list_first_elem(&module_inst->module->fast_opcode_list);
while (fast_opcode) {
if (offset <= fast_opcode->offset
&& fast_opcode->offset < offset + *size) {
@ -696,7 +713,8 @@ wasm_debug_instance_get_linear_mem(WASMDebugInstance *instance, uint64 offset,
LOG_VERBOSE("wasm_debug_instance_get_linear_mem size over flow!\n");
*size = linear_mem_size >= offset ? linear_mem_size - offset : 0;
}
bh_memcpy_s(buf, *size, memory->memory_data + offset, *size);
bh_memcpy_s(buf, (uint32)*size, memory->memory_data + offset,
(uint32)*size);
return true;
}
return false;
@ -728,7 +746,8 @@ wasm_debug_instance_set_linear_mem(WASMDebugInstance *instance, uint64 offset,
LOG_VERBOSE("wasm_debug_instance_get_linear_mem size over flow!\n");
*size = linear_mem_size >= offset ? linear_mem_size - offset : 0;
}
bh_memcpy_s(memory->memory_data + offset, *size, buf, *size);
bh_memcpy_s(memory->memory_data + offset, (uint32)*size, buf,
(uint32)*size);
return true;
}
return false;
@ -785,13 +804,13 @@ wasm_exec_env_get_instance(WASMExecEnv *exec_env)
return instance;
}
int
wasm_debug_instance_get_call_stack_pcs(WASMDebugInstance *instance, uint64 tid,
uint64 buf[], uint64 size)
uint32
wasm_debug_instance_get_call_stack_pcs(WASMDebugInstance *instance,
korp_tid tid, uint64 buf[], uint64 size)
{
WASMExecEnv *exec_env;
struct WASMInterpFrame *frame;
uint64 i = 0;
uint32 i = 0;
if (!instance)
return 0;
@ -948,7 +967,7 @@ wasm_debug_instance_kill(WASMDebugInstance *instance)
}
bool
wasm_debug_instance_singlestep(WASMDebugInstance *instance, uint64 tid)
wasm_debug_instance_singlestep(WASMDebugInstance *instance, korp_tid tid)
{
WASMExecEnv *exec_env;
@ -960,7 +979,7 @@ wasm_debug_instance_singlestep(WASMDebugInstance *instance, uint64 tid)
return false;
while (exec_env) {
if (exec_env->handle == tid || tid == (uint64)~0) {
if (exec_env->handle == tid || tid == (korp_tid)(uintptr_t)~0LL) {
wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_SINGSTEP);
wasm_cluster_thread_step(exec_env);
}
@ -970,16 +989,16 @@ wasm_debug_instance_singlestep(WASMDebugInstance *instance, uint64 tid)
}
bool
wasm_debug_instance_get_local(WASMDebugInstance *instance, int frame_index,
int local_index, char buf[], int *size)
wasm_debug_instance_get_local(WASMDebugInstance *instance, int32 frame_index,
int32 local_index, char buf[], int32 *size)
{
WASMExecEnv *exec_env;
struct WASMInterpFrame *frame;
WASMFunctionInstance *cur_func;
uint8 local_type = 0xFF;
uint32 local_offset;
int param_count;
int fi = 0;
int32 param_count;
int32 fi = 0;
if (!instance)
return false;
@ -1029,8 +1048,8 @@ wasm_debug_instance_get_local(WASMDebugInstance *instance, int frame_index,
}
bool
wasm_debug_instance_get_global(WASMDebugInstance *instance, int frame_index,
int global_index, char buf[], int *size)
wasm_debug_instance_get_global(WASMDebugInstance *instance, int32 frame_index,
int32 global_index, char buf[], int32 *size)
{
WASMExecEnv *exec_env;
struct WASMInterpFrame *frame;
@ -1039,7 +1058,7 @@ wasm_debug_instance_get_global(WASMDebugInstance *instance, int frame_index,
uint8 *global_addr;
uint8 global_type = 0xFF;
uint8 *global_data;
int fi = 0;
int32 fi = 0;
if (!instance)
return false;
@ -1095,7 +1114,8 @@ wasm_debug_instance_get_global(WASMDebugInstance *instance, int frame_index,
}
uint64
wasm_debug_instance_mmap(WASMDebugInstance *instance, uint32 size, int map_port)
wasm_debug_instance_mmap(WASMDebugInstance *instance, uint32 size,
int32 map_port)
{
WASMExecEnv *exec_env;
WASMModuleInstance *module_inst;

View File

@ -87,7 +87,7 @@ WASMDebugInstance *
wasm_exec_env_get_instance(WASMExecEnv *exec_env);
bool
wasm_debug_engine_init(char *ip_addr, int platform_port, int process_port);
wasm_debug_engine_init(char *ip_addr, int32 platform_port, int32 process_port);
void
wasm_debug_engine_destroy();
@ -101,15 +101,15 @@ wasm_debug_get_engine_active(void);
uint64
wasm_debug_instance_get_pid(WASMDebugInstance *instance);
uint64
korp_tid
wasm_debug_instance_get_tid(WASMDebugInstance *instance);
int
wasm_debug_instance_get_tids(WASMDebugInstance *instance, uint64 tids[],
int len);
uint32
wasm_debug_instance_get_tids(WASMDebugInstance *instance, korp_tid tids[],
uint32 len);
void
wasm_debug_instance_set_cur_thread(WASMDebugInstance *instance, uint64 tid);
wasm_debug_instance_set_cur_thread(WASMDebugInstance *instance, korp_tid tid);
uint64
wasm_debug_instance_get_pc(WASMDebugInstance *instance);
@ -140,9 +140,9 @@ bool
wasm_debug_instance_set_mem(WASMDebugInstance *instance, uint64 addr, char *buf,
uint64 *size);
int
wasm_debug_instance_get_call_stack_pcs(WASMDebugInstance *instance, uint64 tid,
uint64 buf[], uint64 size);
uint32
wasm_debug_instance_get_call_stack_pcs(WASMDebugInstance *instance,
korp_tid tid, uint64 buf[], uint64 size);
bool
wasm_debug_instance_add_breakpoint(WASMDebugInstance *instance, uint64 addr,
@ -158,33 +158,34 @@ wasm_debug_instance_continue(WASMDebugInstance *instance);
bool
wasm_debug_instance_kill(WASMDebugInstance *instance);
uint64
wasm_debug_instance_wait_thread(WASMDebugInstance *instance, uint64 tid,
korp_tid
wasm_debug_instance_wait_thread(WASMDebugInstance *instance, korp_tid tid,
uint32 *status);
uint32
wasm_debug_instance_get_thread_status(WASMDebugInstance *instance, uint64 tid);
wasm_debug_instance_get_thread_status(WASMDebugInstance *instance,
korp_tid tid);
bool
wasm_debug_instance_singlestep(WASMDebugInstance *instance, uint64 tid);
wasm_debug_instance_singlestep(WASMDebugInstance *instance, korp_tid tid);
bool
wasm_debug_instance_get_local(WASMDebugInstance *instance, int frame_index,
int local_index, char buf[], int *size);
wasm_debug_instance_get_local(WASMDebugInstance *instance, int32 frame_index,
int32 local_index, char buf[], int32 *size);
bool
wasm_debug_instance_get_global(WASMDebugInstance *instance, int frame_index,
int global_index, char buf[], int *size);
wasm_debug_instance_get_global(WASMDebugInstance *instance, int32 frame_index,
int32 global_index, char buf[], int32 *size);
#if WASM_ENABLE_LIBC_WASI != 0
bool
wasm_debug_instance_get_current_object_name(WASMDebugInstance *instance,
char name_buffer[], int len);
char name_buffer[], uint32 len);
#endif
uint64
wasm_debug_instance_mmap(WASMDebugInstance *instance, uint32 size,
int map_port);
int32 map_port);
bool
wasm_debug_instance_ummap(WASMDebugInstance *instance, uint64 addr);

View File

@ -3,22 +3,8 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_platform.h"
#include "gdbserver.h"
#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <unistd.h>
#include "bh_log.h"
#include "handler.h"
#include "packets.h"
#include "utils.h"
@ -51,14 +37,9 @@ static struct packet_handler_elem packet_handler_table[255] = {
};
WASMGDBServer *
wasm_create_gdbserver(char *host, int *port)
wasm_create_gdbserver(const char *host, int32 *port)
{
int listen_fd = -1;
const int one = 1;
struct sockaddr_in addr;
socklen_t socklen;
int ret;
bh_socket_t listen_fd = (bh_socket_t)-1;
WASMGDBServer *server;
bh_assert(port);
@ -70,52 +51,25 @@ wasm_create_gdbserver(char *host, int *port)
memset(server, 0, sizeof(WASMGDBServer));
listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listen_fd < 0) {
LOG_ERROR("wasm gdb server error: socket() failed");
if (0 != os_socket_create(&listen_fd, 1)) {
LOG_ERROR("wasm gdb server error: create socket failed");
goto fail;
}
ret = fcntl(listen_fd, F_SETFD, FD_CLOEXEC);
if (ret < 0) {
LOG_ERROR(
"wasm gdb server error: fcntl() failed on setting FD_CLOEXEC");
if (0 != os_socket_bind(listen_fd, host, port)) {
LOG_ERROR("wasm gdb server error: socket bind failed");
goto fail;
}
ret = setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if (ret < 0) {
LOG_ERROR("wasm gdb server error: setsockopt() failed");
goto fail;
}
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(host);
addr.sin_port = htons(*port);
ret = bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0) {
LOG_ERROR("wasm gdb server error: bind() failed");
goto fail;
}
socklen = sizeof(addr);
if (getsockname(listen_fd, (void *)&addr, &socklen) == -1) {
LOG_ERROR("%s", strerror(errno));
goto fail;
}
LOG_WARNING("Debug server listening on %s:%d\n", host,
ntohs(addr.sin_port));
*port = ntohs(addr.sin_port);
LOG_WARNING("Debug server listening on %s:%" PRIu32 "\n", host, *port);
server->listen_fd = listen_fd;
return server;
fail:
if (listen_fd >= 0) {
shutdown(listen_fd, SHUT_RDWR);
close(listen_fd);
os_socket_shutdown(listen_fd);
os_socket_close(listen_fd);
}
if (server)
wasm_runtime_free(server);
@ -125,18 +79,18 @@ fail:
bool
wasm_gdbserver_listen(WASMGDBServer *server)
{
int ret;
int sockt_fd = 0;
bh_socket_t sockt_fd = (bh_socket_t)-1;
int32 ret;
ret = listen(server->listen_fd, 1);
if (ret < 0) {
LOG_ERROR("wasm gdb server error: listen() failed");
ret = os_socket_listen(server->listen_fd, 1);
if (ret != 0) {
LOG_ERROR("wasm gdb server error: socket listen failed");
goto fail;
}
sockt_fd = accept(server->listen_fd, NULL, NULL);
os_socket_accept(server->listen_fd, &sockt_fd, NULL, NULL);
if (sockt_fd < 0) {
LOG_ERROR("wasm gdb server error: accept() failed");
LOG_ERROR("wasm gdb server error: socket accept failed");
goto fail;
}
@ -146,8 +100,8 @@ wasm_gdbserver_listen(WASMGDBServer *server)
return true;
fail:
shutdown(server->listen_fd, SHUT_RDWR);
close(server->listen_fd);
os_socket_shutdown(server->listen_fd);
os_socket_close(server->listen_fd);
return false;
}
@ -155,12 +109,12 @@ void
wasm_close_gdbserver(WASMGDBServer *server)
{
if (server->socket_fd > 0) {
shutdown(server->socket_fd, SHUT_RDWR);
close(server->socket_fd);
os_socket_shutdown(server->socket_fd);
os_socket_close(server->socket_fd);
}
if (server->listen_fd > 0) {
shutdown(server->listen_fd, SHUT_RDWR);
close(server->listen_fd);
os_socket_shutdown(server->listen_fd);
os_socket_close(server->listen_fd);
}
}
@ -180,33 +134,34 @@ handler_packet(WASMGDBServer *server, char request, char *payload)
static void
process_packet(WASMGDBServer *server)
{
uint8_t *inbuf = server->pkt.buf;
int inbuf_size = server->pkt.size;
uint8_t *packetend_ptr = (uint8_t *)memchr(inbuf, '#', inbuf_size);
int packetend = packetend_ptr - inbuf;
uint8 *inbuf = server->pkt.buf;
int32 inbuf_size = server->pkt.size;
uint8 *packetend_ptr = (uint8 *)memchr(inbuf, '#', inbuf_size);
int32 packet_size = (int32)(uintptr_t)(packetend_ptr - inbuf);
char request = inbuf[1];
char *payload = NULL;
uint8_t checksum = 0;
uint8 checksum = 0;
if (packetend == 1) {
if (packet_size == 1) {
LOG_VERBOSE("receive empty request, ignore it\n");
return;
}
bh_assert('$' == inbuf[0]);
inbuf[packetend] = '\0';
inbuf[packet_size] = '\0';
for (int i = 1; i < packetend; i++)
for (int i = 1; i < packet_size; i++)
checksum += inbuf[i];
bh_assert(checksum
== (hex(inbuf[packetend + 1]) << 4 | hex(inbuf[packetend + 2])));
bh_assert(
checksum
== (hex(inbuf[packet_size + 1]) << 4 | hex(inbuf[packet_size + 2])));
payload = (char *)&inbuf[2];
LOG_VERBOSE("receive request:%c %s\n", request, payload);
handler_packet(server, request, payload);
inbuf_erase_head(server, packetend + 3);
inbuf_erase_head(server, packet_size + 3);
}
bool

View File

@ -6,7 +6,7 @@
#ifndef _GDB_SERVER_H
#define _GDB_SERVER_H
#include <stdbool.h>
#include "bh_platform.h"
#define PACKET_BUF_SIZE 0x8000
@ -20,20 +20,20 @@ enum GDBStoppointType {
};
typedef struct WasmDebugPacket {
unsigned char buf[PACKET_BUF_SIZE];
unsigned int size;
uint32 size;
} WasmDebugPacket;
struct WASMDebugControlThread;
typedef struct WASMGDBServer {
int listen_fd;
int socket_fd;
bh_socket_t listen_fd;
bh_socket_t socket_fd;
WasmDebugPacket pkt;
bool noack;
struct WASMDebugControlThread *thread;
} WASMGDBServer;
WASMGDBServer *
wasm_create_gdbserver(char *addr, int *port);
wasm_create_gdbserver(const char *host, int32 *port);
bool
wasm_gdbserver_listen(WASMGDBServer *server);

View File

@ -3,12 +3,8 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <bh_log.h>
#include <handler.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>
#include "bh_platform.h"
#include "handler.h"
#include "debug_engine.h"
#include "packets.h"
#include "utils.h"
@ -16,9 +12,22 @@
#define MAX_PACKET_SIZE (0x20000)
static char tmpbuf[MAX_PACKET_SIZE];
static korp_mutex tmpbuf_lock;
int
wasm_debug_handler_init()
{
return os_mutex_init(&tmpbuf_lock);
}
void
wasm_debug_handler_deinit()
{
os_mutex_destroy(&tmpbuf_lock);
}
static void
send_thread_stop_status(WASMGDBServer *server, uint32_t status, uint64_t tid);
send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid);
void
handle_generay_set(WASMGDBServer *server, char *payload)
@ -59,37 +68,40 @@ process_xfer(WASMGDBServer *server, const char *name, char *args)
if (!strcmp(name, "libraries") && !strcmp(mode, "read")) {
// TODO: how to get current wasm file name?
uint64_t addr = wasm_debug_instance_get_load_addr(
uint64 addr = wasm_debug_instance_get_load_addr(
(WASMDebugInstance *)server->thread->debug_instance);
os_mutex_lock(&tmpbuf_lock);
#if WASM_ENABLE_LIBC_WASI != 0
char objname[128];
wasm_debug_instance_get_current_object_name(
(WASMDebugInstance *)server->thread->debug_instance, objname, 128);
sprintf(tmpbuf,
snprintf(tmpbuf, sizeof(tmpbuf),
"l<library-list><library name=\"%s\"><section "
"address=\"0x%lx\"/></library></library-list>",
"address=\"0x%" PRIx64 "\"/></library></library-list>",
objname, addr);
#else
sprintf(tmpbuf,
snprintf(tmpbuf, sizeof(tmpbuf),
"l<library-list><library name=\"%s\"><section "
"address=\"0x%lx\"/></library></library-list>",
"address=\"0x%" PRIx64 "\"/></library></library-list>",
"nobody.wasm", addr);
#endif
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
}
void
porcess_wasm_local(WASMGDBServer *server, char *args)
{
int frame_index;
int local_index;
int32 frame_index;
int32 local_index;
char buf[16];
int size = 16;
int32 size = 16;
bool ret;
sprintf(tmpbuf, "E01");
if (sscanf(args, "%d;%d", &frame_index, &local_index) == 2) {
os_mutex_lock(&tmpbuf_lock);
snprintf(tmpbuf, sizeof(tmpbuf), "E01");
if (sscanf(args, "%" PRId32 ";%" PRId32, &frame_index, &local_index) == 2) {
ret = wasm_debug_instance_get_local(
(WASMDebugInstance *)server->thread->debug_instance, frame_index,
local_index, buf, &size);
@ -98,19 +110,22 @@ porcess_wasm_local(WASMGDBServer *server, char *args)
}
}
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
void
porcess_wasm_global(WASMGDBServer *server, char *args)
{
int frame_index;
int global_index;
int32 frame_index;
int32 global_index;
char buf[16];
int size = 16;
int32 size = 16;
bool ret;
sprintf(tmpbuf, "E01");
if (sscanf(args, "%d;%d", &frame_index, &global_index) == 2) {
os_mutex_lock(&tmpbuf_lock);
snprintf(tmpbuf, sizeof(tmpbuf), "E01");
if (sscanf(args, "%" PRId32 ";%" PRId32, &frame_index, &global_index)
== 2) {
ret = wasm_debug_instance_get_global(
(WASMDebugInstance *)server->thread->debug_instance, frame_index,
global_index, buf, &size);
@ -119,6 +134,7 @@ porcess_wasm_global(WASMGDBServer *server, char *args)
}
}
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
void
@ -126,6 +142,7 @@ handle_generay_query(WASMGDBServer *server, char *payload)
{
const char *name;
char *args;
char triple[256];
args = strchr(payload, ':');
if (args)
@ -134,18 +151,25 @@ handle_generay_query(WASMGDBServer *server, char *payload)
LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
if (!strcmp(name, "C")) {
uint64_t pid, tid;
uint64 pid, tid;
pid = wasm_debug_instance_get_pid(
(WASMDebugInstance *)server->thread->debug_instance);
tid = wasm_debug_instance_get_tid(
tid = (uint64)(uintptr_t)wasm_debug_instance_get_tid(
(WASMDebugInstance *)server->thread->debug_instance);
snprintf(tmpbuf, sizeof(tmpbuf), "QCp%lx.%lx", pid, tid);
os_mutex_lock(&tmpbuf_lock);
snprintf(tmpbuf, sizeof(tmpbuf), "QCp%" PRIx64 ".%" PRIx64 "", pid,
tid);
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
if (!strcmp(name, "Supported")) {
sprintf(tmpbuf, "qXfer:libraries:read+;PacketSize=%x;",
os_mutex_lock(&tmpbuf_lock);
snprintf(tmpbuf, sizeof(tmpbuf),
"qXfer:libraries:read+;PacketSize=%" PRIx32 ";",
MAX_PACKET_SIZE);
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
if (!strcmp(name, "Xfer")) {
@ -166,21 +190,24 @@ handle_generay_query(WASMGDBServer *server, char *payload)
if (!strcmp(name, "HostInfo")) {
// Todo: change vendor to Intel for outside tree
char triple[256];
mem2hex("wasm32-Ant-wasi-wasm", triple, strlen("wasm32-Ant-wasi-wasm"));
sprintf(tmpbuf,
os_mutex_lock(&tmpbuf_lock);
snprintf(tmpbuf, sizeof(tmpbuf),
"vendor:Ant;ostype:wasi;arch:wasm32;"
"triple:%s;endian:little;ptrsize:4;",
triple);
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
if (!strcmp(name, "ModuleInfo")) {
write_packet(server, "");
}
if (!strcmp(name, "GetWorkingDir")) {
os_mutex_lock(&tmpbuf_lock);
if (getcwd(tmpbuf, PATH_MAX))
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
if (!strcmp(name, "QueryGDBServer")) {
write_packet(server, "");
@ -190,25 +217,29 @@ handle_generay_query(WASMGDBServer *server, char *payload)
}
if (!strcmp(name, "ProcessInfo")) {
// Todo: process id parent-pid
uint64_t pid;
uint64 pid;
pid = wasm_debug_instance_get_pid(
(WASMDebugInstance *)server->thread->debug_instance);
char triple[256];
// arch-vendor-os-env(format)
mem2hex("wasm32-Ant-wasi-wasm", triple, strlen("wasm32-Ant-wasi-wasm"));
sprintf(tmpbuf,
"pid:%lx;parent-pid:%lx;vendor:Ant;ostype:wasi;arch:wasm32;"
os_mutex_lock(&tmpbuf_lock);
snprintf(tmpbuf, sizeof(tmpbuf),
"pid:%" PRIx64 ";parent-pid:%" PRIx64
";vendor:Ant;ostype:wasi;arch:wasm32;"
"triple:%s;endian:little;ptrsize:4;",
pid, pid, triple);
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
if (!strcmp(name, "RegisterInfo0")) {
sprintf(
tmpbuf,
os_mutex_lock(&tmpbuf_lock);
snprintf(
tmpbuf, sizeof(tmpbuf),
"name:pc;alt-name:pc;bitsize:64;offset:0;encoding:uint;format:hex;"
"set:General Purpose Registers;gcc:16;dwarf:16;generic:pc;");
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
else if (!strncmp(name, "RegisterInfo", strlen("RegisterInfo"))) {
write_packet(server, "E45");
@ -218,16 +249,22 @@ handle_generay_query(WASMGDBServer *server, char *payload)
}
if (args && (!strcmp(name, "MemoryRegionInfo"))) {
uint64_t addr = strtol(args, NULL, 16);
uint64 addr = strtoll(args, NULL, 16);
WASMDebugMemoryInfo *mem_info = wasm_debug_instance_get_memregion(
(WASMDebugInstance *)server->thread->debug_instance, addr);
if (mem_info) {
char name_buf[256];
mem2hex(mem_info->name, name_buf, strlen(mem_info->name));
sprintf(tmpbuf, "start:%lx;size:%lx;permissions:%s;name:%s;",
os_mutex_lock(&tmpbuf_lock);
snprintf(tmpbuf, sizeof(tmpbuf),
"start:%" PRIx64 ";size:%" PRIx64
";permissions:%s;name:%s;",
(uint64)mem_info->start, mem_info->size,
mem_info->permisson, name_buf);
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
wasm_debug_instance_destroy_memregion(
(WASMDebugInstance *)server->thread->debug_instance, mem_info);
}
@ -244,14 +281,17 @@ handle_generay_query(WASMGDBServer *server, char *payload)
}
if (args && (!strcmp(name, "WasmCallStack"))) {
uint64_t tid = strtol(args, NULL, 16);
uint64_t buf[1024 / sizeof(uint64_t)];
uint64_t count = wasm_debug_instance_get_call_stack_pcs(
(WASMDebugInstance *)server->thread->debug_instance, tid, buf,
1024 / sizeof(uint64_t));
uint64 tid = strtoll(args, NULL, 16);
uint64 buf[1024 / sizeof(uint64)];
uint32 count = wasm_debug_instance_get_call_stack_pcs(
(WASMDebugInstance *)server->thread->debug_instance,
(korp_tid)(uintptr_t)tid, buf, 1024 / sizeof(uint64));
if (count > 0) {
mem2hex((char *)buf, tmpbuf, count * sizeof(uint64_t));
os_mutex_lock(&tmpbuf_lock);
mem2hex((char *)buf, tmpbuf, count * sizeof(uint64));
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
else
write_packet(server, "");
@ -271,9 +311,11 @@ handle_generay_query(WASMGDBServer *server, char *payload)
if (!strncmp(name, "ThreadStopInfo", strlen("ThreadStopInfo"))) {
int32 prefix_len = strlen("ThreadStopInfo");
uint64 tid = strtol(name + prefix_len, NULL, 16);
uint64 tid_number = strtoll(name + prefix_len, NULL, 16);
korp_tid tid = (korp_tid)(uintptr_t)tid_number;
uint32 status;
uint32 status = wasm_debug_instance_get_thread_status(
status = wasm_debug_instance_get_thread_status(
server->thread->debug_instance, tid);
send_thread_stop_status(server, status, tid);
@ -281,37 +323,44 @@ handle_generay_query(WASMGDBServer *server, char *payload)
}
static void
send_thread_stop_status(WASMGDBServer *server, uint32_t status, uint64_t tid)
send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid)
{
int tids_number, len = 0, i = 0;
uint64_t tids[20];
int32 len = 0;
uint64 pc;
korp_tid tids[20];
char pc_string[17];
uint32_t gdb_status = status;
uint32 tids_count, i = 0;
uint32 gdb_status = status;
if (status == 0) {
sprintf(tmpbuf, "W%02x", status);
os_mutex_lock(&tmpbuf_lock);
snprintf(tmpbuf, sizeof(tmpbuf), "W%02x", status);
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
return;
}
tids_number = wasm_debug_instance_get_tids(
tids_count = wasm_debug_instance_get_tids(
(WASMDebugInstance *)server->thread->debug_instance, tids, 20);
uint64_t pc = wasm_debug_instance_get_pc(
pc = wasm_debug_instance_get_pc(
(WASMDebugInstance *)server->thread->debug_instance);
if (status == WAMR_SIG_SINGSTEP) {
gdb_status = WAMR_SIG_TRAP;
}
os_mutex_lock(&tmpbuf_lock);
// TODO: how name a wasm thread?
len +=
sprintf(tmpbuf, "T%02xthread:%lx;name:%s;", gdb_status, tid, "nobody");
if (tids_number > 0) {
len += sprintf(tmpbuf + len, "threads:");
while (i < tids_number) {
if (i == tids_number - 1)
len += sprintf(tmpbuf + len, "%lx;", tids[i]);
len += snprintf(tmpbuf, sizeof(tmpbuf), "T%02xthread:%" PRIx64 ";name:%s;",
gdb_status, (uint64)(uintptr_t)tid, "nobody");
if (tids_count > 0) {
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, "threads:");
while (i < tids_count) {
if (i == tids_count - 1)
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len,
"%" PRIx64 ";", (uint64)(uintptr_t)tids[i]);
else
len += sprintf(tmpbuf + len, "%lx,", tids[i]);
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len,
"%" PRIx64 ",", (uint64)(uintptr_t)tids[i]);
i++;
}
}
@ -319,18 +368,22 @@ send_thread_stop_status(WASMGDBServer *server, uint32_t status, uint64_t tid)
pc_string[8 * 2] = '\0';
if (status == WAMR_SIG_TRAP) {
len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len,
"thread-pcs:%" PRIx64 ";00:%s,reason:%s;", pc,
pc_string, "breakpoint");
}
else if (status == WAMR_SIG_SINGSTEP) {
len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len,
"thread-pcs:%" PRIx64 ";00:%s,reason:%s;", pc,
pc_string, "trace");
}
else if (status > 0) {
len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len,
"thread-pcs:%" PRIx64 ";00:%s,reason:%s;", pc,
pc_string, "signal");
}
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
void
@ -338,7 +391,8 @@ handle_v_packet(WASMGDBServer *server, char *payload)
{
const char *name;
char *args;
uint32_t status;
uint32 status;
args = strchr(payload, ';');
if (args)
*args++ = '\0';
@ -353,8 +407,12 @@ handle_v_packet(WASMGDBServer *server, char *payload)
if (args[0] == 's' || args[0] == 'c') {
char *numstring = strchr(args, ':');
if (numstring) {
uint64 tid_number;
korp_tid tid;
*numstring++ = '\0';
uint64_t tid = strtol(numstring, NULL, 16);
tid_number = strtoll(numstring, NULL, 16);
tid = (korp_tid)(uintptr_t)tid_number;
wasm_debug_instance_set_cur_thread(
(WASMDebugInstance *)server->thread->debug_instance,
tid);
@ -383,9 +441,9 @@ handle_v_packet(WASMGDBServer *server, char *payload)
void
handle_threadstop_request(WASMGDBServer *server, char *payload)
{
uint64_t tid = wasm_debug_instance_get_tid(
korp_tid tid = wasm_debug_instance_get_tid(
(WASMDebugInstance *)server->thread->debug_instance);
uint32_t status;
uint32 status;
tid = wasm_debug_instance_wait_thread(
(WASMDebugInstance *)server->thread->debug_instance, tid, &status);
@ -398,11 +456,11 @@ handle_set_current_thread(WASMGDBServer *server, char *payload)
{
LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload, payload);
if ('g' == *payload++) {
uint64_t tid;
tid = strtol(payload, NULL, 16);
uint64 tid = strtoll(payload, NULL, 16);
if (tid > 0)
wasm_debug_instance_set_cur_thread(
(WASMDebugInstance *)server->thread->debug_instance, tid);
(WASMDebugInstance *)server->thread->debug_instance,
(korp_tid)(uintptr_t)tid);
}
write_packet(server, "OK");
}
@ -410,17 +468,21 @@ handle_set_current_thread(WASMGDBServer *server, char *payload)
void
handle_get_register(WASMGDBServer *server, char *payload)
{
int i = strtol(payload, NULL, 16);
uint64 regdata;
int32 i = strtol(payload, NULL, 16);
if (i != 0) {
write_packet(server, "E01");
return;
}
uint64_t regdata = wasm_debug_instance_get_pc(
regdata = wasm_debug_instance_get_pc(
(WASMDebugInstance *)server->thread->debug_instance);
os_mutex_lock(&tmpbuf_lock);
mem2hex((void *)&regdata, tmpbuf, 8);
tmpbuf[8 * 2] = '\0';
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
void
@ -443,16 +505,20 @@ handle_get_read_binary_memory(WASMGDBServer *server, char *payload)
void
handle_get_read_memory(WASMGDBServer *server, char *payload)
{
size_t maddr, mlen;
uint64 maddr, mlen;
bool ret;
sprintf(tmpbuf, "%s", "");
if (sscanf(payload, "%zx,%zx", &maddr, &mlen) == 2) {
os_mutex_lock(&tmpbuf_lock);
snprintf(tmpbuf, sizeof(tmpbuf), "%s", "");
if (sscanf(payload, "%" SCNx64 ",%" SCNx64, &maddr, &mlen) == 2) {
char *buff;
if (mlen * 2 > MAX_PACKET_SIZE) {
LOG_ERROR("Buffer overflow!");
mlen = MAX_PACKET_SIZE / 2;
}
char *buff = wasm_runtime_malloc(mlen);
buff = wasm_runtime_malloc(mlen);
if (buff) {
ret = wasm_debug_instance_get_mem(
(WASMDebugInstance *)server->thread->debug_instance, maddr,
@ -464,21 +530,26 @@ handle_get_read_memory(WASMGDBServer *server, char *payload)
}
}
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
void
handle_get_write_memory(WASMGDBServer *server, char *payload)
{
size_t maddr, mlen, hex_len;
int offset, act_len;
size_t hex_len;
int32 offset, act_len;
uint64 maddr, mlen;
char *buff;
bool ret;
sprintf(tmpbuf, "%s", "");
if (sscanf(payload, "%zx,%zx:%n", &maddr, &mlen, &offset) == 2) {
os_mutex_lock(&tmpbuf_lock);
snprintf(tmpbuf, sizeof(tmpbuf), "%s", "");
if (sscanf(payload, "%" SCNx64 ",%" SCNx64 ":%n", &maddr, &mlen, &offset)
== 2) {
payload += offset;
hex_len = strlen(payload);
act_len = hex_len / 2 < mlen ? hex_len / 2 : mlen;
buff = wasm_runtime_malloc(act_len);
if (buff) {
hex2mem(payload, buff, act_len);
@ -486,20 +557,22 @@ handle_get_write_memory(WASMGDBServer *server, char *payload)
(WASMDebugInstance *)server->thread->debug_instance, maddr,
buff, &mlen);
if (ret) {
sprintf(tmpbuf, "%s", "OK");
snprintf(tmpbuf, sizeof(tmpbuf), "%s", "OK");
}
wasm_runtime_free(buff);
}
}
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
void
handle_add_break(WASMGDBServer *server, char *payload)
{
size_t type, addr, length;
size_t type, length;
uint64 addr;
if (sscanf(payload, "%zx,%zx,%zx", &type, &addr, &length) == 3) {
if (sscanf(payload, "%zx,%" SCNx64 ",%zx", &type, &addr, &length) == 3) {
if (type == eBreakpointSoftware) {
bool ret = wasm_debug_instance_add_breakpoint(
(WASMDebugInstance *)server->thread->debug_instance, addr,
@ -517,9 +590,10 @@ handle_add_break(WASMGDBServer *server, char *payload)
void
handle_remove_break(WASMGDBServer *server, char *payload)
{
size_t type, addr, length;
size_t type, length;
uint64 addr;
if (sscanf(payload, "%zx,%zx,%zx", &type, &addr, &length) == 3) {
if (sscanf(payload, "%zx,%" SCNx64 ",%zx", &type, &addr, &length) == 3) {
if (type == eBreakpointSoftware) {
bool ret = wasm_debug_instance_remove_breakpoint(
(WASMDebugInstance *)server->thread->debug_instance, addr,
@ -537,8 +611,8 @@ handle_remove_break(WASMGDBServer *server, char *payload)
void
handle_continue_request(WASMGDBServer *server, char *payload)
{
uint64_t tid;
uint32_t status;
korp_tid tid;
uint32 status;
wasm_debug_instance_continue(
(WASMDebugInstance *)server->thread->debug_instance);
@ -555,8 +629,8 @@ handle_continue_request(WASMGDBServer *server, char *payload)
void
handle_kill_request(WASMGDBServer *server, char *payload)
{
uint64_t tid;
uint32_t status;
korp_tid tid;
uint32 status;
wasm_debug_instance_kill(
(WASMDebugInstance *)server->thread->debug_instance);
@ -574,11 +648,8 @@ static void
handle_malloc(WASMGDBServer *server, char *payload)
{
char *args;
uint64_t size;
int map_port = MMAP_PROT_NONE;
uint64_t addr;
sprintf(tmpbuf, "%s", "E03");
uint64 addr, size;
int32 map_port = MMAP_PROT_NONE;
args = strstr(payload, ",");
if (args) {
@ -589,7 +660,10 @@ handle_malloc(WASMGDBServer *server, char *payload)
return;
}
size = strtol(payload, NULL, 16);
os_mutex_lock(&tmpbuf_lock);
snprintf(tmpbuf, sizeof(tmpbuf), "%s", "E03");
size = strtoll(payload, NULL, 16);
if (size > 0) {
while (*args) {
if (*args == 'r') {
@ -607,27 +681,31 @@ handle_malloc(WASMGDBServer *server, char *payload)
(WASMDebugInstance *)server->thread->debug_instance, size,
map_port);
if (addr) {
sprintf(tmpbuf, "%lx", addr);
snprintf(tmpbuf, sizeof(tmpbuf), "%" PRIx64, addr);
}
}
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
static void
handle_free(WASMGDBServer *server, char *payload)
{
uint64_t addr;
uint64 addr;
bool ret;
sprintf(tmpbuf, "%s", "E03");
addr = strtol(payload, NULL, 16);
os_mutex_lock(&tmpbuf_lock);
snprintf(tmpbuf, sizeof(tmpbuf), "%s", "E03");
addr = strtoll(payload, NULL, 16);
ret = wasm_debug_instance_ummap(
(WASMDebugInstance *)server->thread->debug_instance, addr);
if (ret) {
sprintf(tmpbuf, "%s", "OK");
snprintf(tmpbuf, sizeof(tmpbuf), "%s", "OK");
}
write_packet(server, tmpbuf);
os_mutex_unlock(&tmpbuf_lock);
}
void

View File

@ -8,6 +8,12 @@
#include "gdbserver.h"
int
wasm_debug_handler_init();
void
wasm_debug_handler_deinit();
void
handle_generay_set(WASMGDBServer *server, char *payload);

View File

@ -3,15 +3,12 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_platform.h"
#include "packets.h"
#include <stdbool.h>
#include "bh_log.h"
#include "gdbserver.h"
void
pktbuf_insert(WASMGDBServer *gdbserver, const uint8_t *buf, ssize_t len)
pktbuf_insert(WASMGDBServer *gdbserver, const uint8 *buf, ssize_t len)
{
WasmDebugPacket *pkt = &gdbserver->pkt;
@ -45,13 +42,13 @@ pktbuf_clear(WASMGDBServer *gdbserver)
pkt->size = 0;
}
int
int32
read_data_once(WASMGDBServer *gdbserver)
{
ssize_t nread;
uint8_t buf[4096];
uint8 buf[4096];
nread = read(gdbserver->socket_fd, buf, sizeof(buf));
nread = os_socket_recv(gdbserver->socket_fd, buf, sizeof(buf));
if (nread <= 0) {
LOG_ERROR("Connection closed");
return -1;
@ -61,11 +58,11 @@ read_data_once(WASMGDBServer *gdbserver)
}
void
write_data_raw(WASMGDBServer *gdbserver, const uint8_t *data, ssize_t len)
write_data_raw(WASMGDBServer *gdbserver, const uint8 *data, ssize_t len)
{
ssize_t nwritten;
nwritten = write(gdbserver->socket_fd, data, len);
nwritten = os_socket_send(gdbserver->socket_fd, data, len);
if (nwritten < 0) {
LOG_ERROR("Write error\n");
exit(-2);
@ -79,21 +76,21 @@ write_hex(WASMGDBServer *gdbserver, unsigned long hex)
size_t len;
len = snprintf(buf, sizeof(buf) - 1, "%02lx", hex);
write_data_raw(gdbserver, (uint8_t *)buf, len);
write_data_raw(gdbserver, (uint8 *)buf, len);
}
void
write_packet_bytes(WASMGDBServer *gdbserver, const uint8_t *data,
write_packet_bytes(WASMGDBServer *gdbserver, const uint8 *data,
size_t num_bytes)
{
uint8_t checksum;
uint8 checksum;
size_t i;
write_data_raw(gdbserver, (uint8_t *)"$", 1);
write_data_raw(gdbserver, (uint8 *)"$", 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_data_raw(gdbserver, (uint8 *)data, num_bytes);
write_data_raw(gdbserver, (uint8 *)"#", 1);
write_hex(gdbserver, checksum);
}
@ -101,17 +98,17 @@ void
write_packet(WASMGDBServer *gdbserver, const char *data)
{
LOG_VERBOSE("send replay:%s", data);
write_packet_bytes(gdbserver, (const uint8_t *)data, strlen(data));
write_packet_bytes(gdbserver, (const uint8 *)data, strlen(data));
}
void
write_binary_packet(WASMGDBServer *gdbserver, const char *pfx,
const uint8_t *data, ssize_t num_bytes)
const uint8 *data, ssize_t num_bytes)
{
uint8_t *buf;
uint8 *buf;
ssize_t pfx_num_chars = strlen(pfx);
ssize_t buf_num_bytes = 0, total_size;
int i;
int32 i;
total_size = 2 * num_bytes + pfx_num_chars;
buf = wasm_runtime_malloc(total_size);
@ -125,7 +122,7 @@ write_binary_packet(WASMGDBServer *gdbserver, const char *pfx,
buf_num_bytes += pfx_num_chars;
for (i = 0; i < num_bytes; ++i) {
uint8_t b = data[i];
uint8 b = data[i];
switch (b) {
case '#':
case '$':
@ -148,7 +145,7 @@ skip_to_packet_start(WASMGDBServer *gdbserver)
{
ssize_t start_index = -1, i;
for (i = 0; i < gdbserver->pkt.size; ++i) {
for (i = 0; i < (ssize_t)gdbserver->pkt.size; ++i) {
if (gdbserver->pkt.buf[i] == '$') {
start_index = i;
break;
@ -176,6 +173,6 @@ read_packet(WASMGDBServer *gdbserver)
return false;
}
if (!gdbserver->noack)
write_data_raw(gdbserver, (uint8_t *)"+", 1);
write_data_raw(gdbserver, (uint8 *)"+", 1);
return true;
}

View File

@ -6,8 +6,6 @@
#ifndef PACKETS_H
#define PACKETS_H
#include <stdint.h>
#include <unistd.h>
#include "gdbserver.h"
bool

View File

@ -5,7 +5,9 @@
#include "utils.h"
int
static const char hexchars[] = "0123456789abcdef";
int32
hex(char ch)
{
if ((ch >= 'a') && (ch <= 'f'))
@ -18,9 +20,9 @@ hex(char ch)
}
char *
mem2hex(char *mem, char *buf, int count)
mem2hex(char *mem, char *buf, int32 count)
{
unsigned char ch;
uint8 ch;
for (int i = 0; i < count; i++) {
ch = *(mem++);
@ -32,9 +34,9 @@ mem2hex(char *mem, char *buf, int count)
}
char *
hex2mem(char *buf, char *mem, int count)
hex2mem(char *buf, char *mem, int32 count)
{
unsigned char ch;
uint8 ch;
for (int i = 0; i < count; i++) {
ch = hex(*buf++) << 4;

View File

@ -6,18 +6,18 @@
#ifndef UTILS_H
#define UTILS_H
static const char hexchars[] = "0123456789abcdef";
#include "bh_platform.h"
int
int32
hex(char ch);
char *
mem2hex(char *mem, char *buf, int count);
mem2hex(char *mem, char *buf, int32 count);
char *
hex2mem(char *buf, char *mem, int count);
hex2mem(char *buf, char *mem, int32 count);
int
unescape(char *msg, int len);
int32
unescape(char *msg, int32 len);
#endif /* UTILS_H */

View File

@ -58,6 +58,8 @@ typedef pthread_t korp_thread;
#define os_thread_local_attribute __thread
#define bh_socket_t int
#if WASM_DISABLE_HW_BOUND_CHECK == 0
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
|| defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \

View File

@ -0,0 +1,124 @@
/*
* Copyright (C) 2021 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "platform_api_vmcore.h"
#include "platform_api_extension.h"
#include <arpa/inet.h>
int
os_socket_create(bh_socket_t *sock, int tcp_or_udp)
{
if (!sock) {
return BHT_ERROR;
}
if (1 == tcp_or_udp) {
*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
}
else if (0 == tcp_or_udp) {
*sock = socket(AF_INET, SOCK_DGRAM, 0);
}
return (*sock == -1) ? BHT_ERROR : BHT_OK;
}
int
os_socket_bind(bh_socket_t socket, const char *host, int *port)
{
struct sockaddr_in addr;
struct linger ling;
socklen_t socklen;
int ret;
assert(host);
assert(port);
ling.l_onoff = 1;
ling.l_linger = 0;
ret = fcntl(socket, F_SETFD, FD_CLOEXEC);
if (ret < 0) {
goto fail;
}
ret = setsockopt(socket, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
if (ret < 0) {
goto fail;
}
addr.sin_addr.s_addr = inet_addr(host);
addr.sin_port = htons(*port);
addr.sin_family = AF_INET;
ret = bind(socket, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0) {
goto fail;
}
socklen = sizeof(addr);
if (getsockname(socket, (void *)&addr, &socklen) == -1) {
goto fail;
}
*port = ntohs(addr.sin_port);
return BHT_OK;
fail:
return BHT_ERROR;
}
int
os_socket_listen(bh_socket_t socket, int max_client)
{
if (listen(socket, max_client) != 0) {
return BHT_ERROR;
}
return BHT_OK;
}
int
os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
unsigned int *addrlen)
{
struct sockaddr addr_tmp;
unsigned int len = sizeof(struct sockaddr);
*sock = accept(server_sock, (struct sockaddr *)&addr_tmp, &len);
if (*sock < 0) {
return BHT_ERROR;
}
return BHT_OK;
}
int
os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
{
return recv(socket, buf, len, 0);
}
int
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
{
return send(socket, buf, len, 0);
}
int
os_socket_close(bh_socket_t socket)
{
close(socket);
return BHT_OK;
}
int
os_socket_shutdown(bh_socket_t socket)
{
shutdown(socket, O_RDWR);
return BHT_OK;
}

View File

@ -59,6 +59,8 @@ typedef pthread_t korp_thread;
#define os_thread_local_attribute __thread
#define bh_socket_t int
#if WASM_DISABLE_HW_BOUND_CHECK == 0
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
|| defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \

View File

@ -23,6 +23,11 @@ extern "C" {
* *
***************************************************/
/****************************************************
* Section 1 *
* Multi thread support *
****************************************************/
/**
* NOTES:
* 1. If you are building VM core only, it must be implemented to
@ -174,6 +179,116 @@ os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds);
int
os_cond_signal(korp_cond *cond);
/****************************************************
* Section 2 *
* Socket support *
****************************************************/
/**
* NOTES:
* Socket APIs are required by source debugging feature.
* If you don't need source debugging feature, then no
* need to implement these APIs
*/
/**
* Create a socket
*
* @param sock [OUTPUT] the pointer of socket
* @param tcp_or_udp 1 for tcp, 0 for udp
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_create(bh_socket_t *sock, int tcp_or_udp);
/**
* Assign the address and port to the socket
*
* @param socket the socket to bind
* @param addr the ip address, only IPv4 supported currently
* @param port [INPUT/OUTPUT] the port number, if the value is 0,
* it will use a port assigned by OS. On return it will
* contain the actual bound port number
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_bind(bh_socket_t socket, const char *addr, int *port);
/**
* Make the socket as a passive socket to accept incoming connection requests
*
* @param socket the socket to listen
* @param max_client maximum clients
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_listen(bh_socket_t socket, int max_client);
/**
* Accept an incoming connection
*
* @param server_sock the socket to accept new connections
* @param sock [OUTPUT] the connected socket
* @param addr [OUTPUT] the address of the peer socket. If addr is NULL,
* nothing is filled in, and addrlen will not be used
* @param addrlen [INPUT/OUTPUT] the size (in bytes) of the structure
* pointed to by addr, on return it will contain the actual
* size of the peer address
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
unsigned int *addrlen);
/**
* Blocking receive message from a socket.
*
* @param socket the socket to receive message from
* @param buf the buffer to store the data
* @param len length of the buffer, this API does not guarantee that
* [len] bytes are received
*
* @return number of bytes received if success, -1 otherwise
*/
int
os_socket_recv(bh_socket_t socket, void *buf, unsigned int len);
/**
* Blocking send message on a socket
*
* @param socket the socket to send message
* @param buf the buffer of data to be sent
* @param len length of the buffer
*
* @return number of bytes sent if success, -1 otherwise
*/
int
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len);
/**
* Close a socket
*
* @param socket the socket to be closed
*
* @return always return 0
*/
int
os_socket_close(bh_socket_t socket);
/**
* Shutdown a socket
*
* @param socket the socket to be shutdown
*
* @return always return 0
*/
int
os_socket_shutdown(bh_socket_t socket);
#ifdef __cplusplus
}
#endif

View File

@ -104,6 +104,25 @@ typedef int64_t int64;
typedef void *(*thread_start_routine_t)(void *);
#ifndef bh_socket_t
/* If no socket defined on current platform,
give a fake definition to make the compiler happy */
#define bh_socket_t int
#endif
/* Format specifiers macros in case
they are not provided by compiler */
#ifndef __PRI64_PREFIX
#if UINTPTR_MAX == UINT64_MAX
#define __PRI64_PREFIX "l"
#define __PRIPTR_PREFIX "l"
#else
#define __PRI64_PREFIX "ll"
#define __PRIPTR_PREFIX
#endif
#endif /* #ifndef __PRI64_PREFIX */
/* Macros for printing format specifiers */
#ifndef PRId32
#define PRId32 "d"
#endif
@ -120,16 +139,6 @@ typedef void *(*thread_start_routine_t)(void *);
#define PRIX32 "X"
#endif
#ifndef __PRI64_PREFIX
#if UINTPTR_MAX == UINT64_MAX
#define __PRI64_PREFIX "l"
#define __PRIPTR_PREFIX "l"
#else
#define __PRI64_PREFIX "ll"
#define __PRIPTR_PREFIX
#endif
#endif
#ifndef PRId64
#define PRId64 __PRI64_PREFIX "d"
#endif
@ -142,10 +151,40 @@ typedef void *(*thread_start_routine_t)(void *);
#ifndef PRIX64
#define PRIX64 __PRI64_PREFIX "X"
#endif
#ifndef PRIxPTR
#define PRIxPTR __PRIPTR_PREFIX "x"
#endif
#ifndef PRIXPTR
#define PRIXPTR __PRIPTR_PREFIX "X"
#endif
/* Macros for scanning format specifiers */
#ifndef SCNd32
#define SCNd32 "d"
#endif
#ifndef SCNi32
#define SCNi32 "i"
#endif
#ifndef SCNu32
#define SCNu32 "u"
#endif
#ifndef SCNx32
#define SCNx32 "x"
#endif
#ifndef SCNd64
#define SCNd64 __PRI64_PREFIX "d"
#endif
#ifndef SCNu64
#define SCNu64 __PRI64_PREFIX "u"
#endif
#ifndef SCNx64
#define SCNx64 __PRI64_PREFIX "x"
#endif
#ifndef SCNxPTR
#define SCNxPTR __PRIPTR_PREFIX "x"
#endif
#ifdef __cplusplus
}
#endif

View File

@ -58,6 +58,8 @@ typedef pthread_t korp_thread;
#define os_thread_local_attribute __thread
#define bh_socket_t int
#if WASM_DISABLE_HW_BOUND_CHECK == 0
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
|| defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \

View File

@ -11,15 +11,27 @@ os_thread_sys_init();
void
os_thread_sys_destroy();
int
init_winsock();
void
deinit_winsock();
int
bh_platform_init()
{
if (init_winsock() != 0) {
return -1;
}
return os_thread_sys_init();
}
void
bh_platform_destroy()
{
deinit_winsock();
os_thread_sys_destroy();
}

View File

@ -26,6 +26,8 @@
#include <malloc.h>
#include <process.h>
#include <Windows.h>
#include <BaseTsd.h>
#include <winsock2.h>
#ifdef __cplusplus
extern "C" {
@ -35,12 +37,20 @@ extern "C" {
#define BH_PLATFORM_WINDOWS
#endif
#ifdef _MSC_VER
#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
#endif
#endif /* #ifdef _MSC_VER */
/* Stack size of applet threads's native part. */
#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024)
/* Default thread priority */
#define BH_THREAD_DEFAULT_PRIORITY 0
typedef SSIZE_T ssize_t;
typedef void *korp_thread;
typedef void *korp_tid;
typedef void *korp_mutex;
@ -53,6 +63,8 @@ typedef struct korp_cond {
os_thread_wait_list thread_wait_list;
} korp_cond;
#define bh_socket_t SOCKET
unsigned
os_getpagesize();
void *

View File

@ -0,0 +1,140 @@
/*
* Copyright (C) 2021 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "platform_api_vmcore.h"
#include "platform_api_extension.h"
/* link with Ws2_32.lib */
#pragma comment(lib, "ws2_32.lib")
static bool is_winsock_inited = false;
int
init_winsock()
{
WSADATA wsaData;
if (!is_winsock_inited) {
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
os_printf("winsock init failed");
return BHT_ERROR;
}
is_winsock_inited = true;
}
return BHT_OK;
}
void
deinit_winsock()
{
if (is_winsock_inited) {
WSACleanup();
}
}
int
os_socket_create(bh_socket_t *sock, int tcp_or_udp)
{
if (!sock) {
return BHT_ERROR;
}
if (1 == tcp_or_udp) {
*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
}
else if (0 == tcp_or_udp) {
*sock = socket(AF_INET, SOCK_DGRAM, 0);
}
return (*sock == -1) ? BHT_ERROR : BHT_OK;
}
int
os_socket_bind(bh_socket_t socket, const char *host, int *port)
{
struct sockaddr_in addr;
int socklen, ret;
assert(host);
assert(port);
addr.sin_addr.s_addr = inet_addr(host);
addr.sin_port = htons(*port);
addr.sin_family = AF_INET;
ret = bind(socket, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0) {
goto fail;
}
socklen = sizeof(addr);
if (getsockname(socket, (void *)&addr, &socklen) == -1) {
os_printf("getsockname failed with error %d\n", WSAGetLastError());
goto fail;
}
*port = ntohs(addr.sin_port);
return BHT_OK;
fail:
return BHT_ERROR;
}
int
os_socket_listen(bh_socket_t socket, int max_client)
{
if (listen(socket, max_client) != 0) {
os_printf("socket listen failed with error %d\n", WSAGetLastError());
return BHT_ERROR;
}
return BHT_OK;
}
int
os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
unsigned int *addrlen)
{
struct sockaddr addr_tmp;
unsigned int len = sizeof(struct sockaddr);
*sock = accept(server_sock, (struct sockaddr *)&addr_tmp, &len);
if (*sock < 0) {
os_printf("socket accept failed with error %d\n", WSAGetLastError());
return BHT_ERROR;
}
return BHT_OK;
}
int
os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
{
return recv(socket, buf, len, 0);
}
int
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
{
return send(socket, buf, len, 0);
}
int
os_socket_close(bh_socket_t socket)
{
closesocket(socket);
return BHT_OK;
}
int
os_socket_shutdown(bh_socket_t socket)
{
shutdown(socket, SD_BOTH);
return BHT_OK;
}

View File

@ -92,6 +92,7 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWIN32_LEAN_AND_MEAN")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")

View File

@ -45,6 +45,10 @@ print_help()
#endif
#if WASM_ENABLE_LIB_PTHREAD != 0
printf(" --max-threads=n Set maximum thread number per cluster, default is 4\n");
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
printf(" -g=ip:port Set the debug sever address, default is debug disabled\n");
printf(" if port is 0, then a random port will be used\n");
#endif
return 1;
}
@ -236,6 +240,11 @@ main(int argc, char *argv[])
const char *env_list[8] = { NULL };
uint32 env_list_size = 0;
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
char *ip_addr = NULL;
/* int platform_port = 0; */
int instance_port = 0;
#endif
/* Process options. */
for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
@ -313,6 +322,19 @@ main(int argc, char *argv[])
return print_help();
wasm_runtime_set_max_thread_num(atoi(argv[0] + 14));
}
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
else if (!strncmp(argv[0], "-g=", 3)) {
char *port_str = strchr(argv[0] + 3, ':');
char *port_end;
if (port_str == NULL)
return print_help();
*port_str = '\0';
instance_port = strtoul(port_str + 1, &port_end, 10);
if (port_str[1] == '\0' || *port_end != '\0')
return print_help();
ip_addr = argv[0] + 3;
}
#endif
else
return print_help();
@ -338,6 +360,13 @@ main(int argc, char *argv[])
init_args.mem_alloc_option.allocator.free_func = free;
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
init_args.platform_port = 0;
init_args.instance_port = instance_port;
if (ip_addr)
strcpy(init_args.ip_addr, ip_addr);
#endif
/* initialize runtime environment */
if (!wasm_runtime_full_init(&init_args)) {
printf("Init runtime environment failed.\n");