From 1bd3bc3a002f9dc90a2706bb46cf94fde4e29351 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Mon, 1 Aug 2022 19:58:10 -0500 Subject: [PATCH] connections work from a remote source --- include/ovm_debug.h | 4 +- src/debug/debug_host.c | 45 +--------- src/debug/debug_info_builder.c | 3 + src/debug/debug_thread.c | 151 +++++++++++++++++++++++++++++++++ src/vm/vm.c | 18 ++++ 5 files changed, 176 insertions(+), 45 deletions(-) create mode 100644 src/debug/debug_thread.c diff --git a/include/ovm_debug.h b/include/ovm_debug.h index b58aed2..41a9879 100644 --- a/include/ovm_debug.h +++ b/include/ovm_debug.h @@ -89,7 +89,7 @@ typedef enum debug_exec_state_t { debug_state_starting, debug_state_ready, debug_state_running, - debug_state_paused + debug_state_paused, } debug_exec_state_t; typedef struct debug_thread_state_t { @@ -129,4 +129,6 @@ void debug_host_stop(debug_state_t *debug); u32 debug_host_register_thread(debug_state_t *debug, struct ovm_state_t *ovm_state); debug_thread_state_t *debug_host_lookup_thread(debug_state_t *debug, u32 id); +void *__debug_thread_entry(void *); + #endif diff --git a/src/debug/debug_host.c b/src/debug/debug_host.c index f6f0522..fafdcfc 100644 --- a/src/debug/debug_host.c +++ b/src/debug/debug_host.c @@ -16,12 +16,10 @@ void debug_host_init(debug_state_t *debug) { debug->client_fd = 0; } -static void *debug_thread_entry(void *); - void debug_host_start(debug_state_t *debug) { if (debug->debug_thread_running) return; - pthread_create(&debug->debug_thread, NULL, debug_thread_entry, debug); + pthread_create(&debug->debug_thread, NULL, __debug_thread_entry, debug); } void debug_host_stop(debug_state_t *debug) { @@ -54,44 +52,3 @@ debug_thread_state_t *debug_host_lookup_thread(debug_state_t *debug, u32 id) { return NULL; } - -#include -#include -#include - -static void *debug_thread_entry(void *data) { - debug_state_t *debug = data; - debug->debug_thread_running = true; - - // Set up socket listener - // Wait for initial connection/handshake before entering loop? - - debug->listen_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); - - struct sockaddr_un local_addr, remote_addr; - local_addr.sun_family = AF_UNIX; - strcpy(local_addr.sun_path, "/tmp/ovm-debug.0000"); // TODO: Make this dynamic so mulitple servers can exist at a time. - unlink(local_addr.sun_path); // TODO: Remove this line for the same reason. - int len = strlen(local_addr.sun_path) + sizeof(local_addr.sun_family); - bind(debug->listen_socket_fd, (struct sockaddr *)&local_addr, len); - - // - // Currently, there can only be 1 connected debugger instance at a time. - listen(debug->listen_socket_fd, 1); - - len = sizeof(struct sockaddr_un); - debug->client_fd = accept(debug->listen_socket_fd, (void * restrict)&remote_addr, &len); - - close(debug->listen_socket_fd); - - printf("Client connected"); - - while (debug->debug_thread_running) { - // ... - - } - - close(debug->client_fd); - - return NULL; -} diff --git a/src/debug/debug_info_builder.c b/src/debug/debug_info_builder.c index d920af8..28855f5 100644 --- a/src/debug/debug_info_builder.c +++ b/src/debug/debug_info_builder.c @@ -96,6 +96,7 @@ void debug_info_builder_emit_location(debug_info_builder_t *builder) { } void debug_info_builder_begin_func(debug_info_builder_t *builder, i32 func_idx) { + if (!builder->data) return; if (func_idx >= bh_arr_length(builder->info->funcs)) return; debug_func_info_t *func_info = &builder->info->funcs[func_idx]; @@ -108,6 +109,8 @@ void debug_info_builder_begin_func(debug_info_builder_t *builder, i32 func_idx) } void debug_info_builder_end_func(debug_info_builder_t *builder) { + if (!builder->data) return; + assert(!builder->locked); debug_info_builder_step(builder); assert(builder->locked); diff --git a/src/debug/debug_thread.c b/src/debug/debug_thread.c new file mode 100644 index 0000000..8ef3220 --- /dev/null +++ b/src/debug/debug_thread.c @@ -0,0 +1,151 @@ + +#include "ovm_debug.h" +#include "vm.h" + +#include +#include +#include + + + +#define CMD_NOP 0 +#define CMD_RES 1 +#define CMD_BRK 2 + +struct msg_parse_ctx_t { + char *data; + unsigned int offset; + unsigned int bytes_read; +}; + +static void send_empty_response(debug_state_t *debug, unsigned int message_number) { + char message_buf[5]; + message_buf[0] = 1; + message_buf[1] = (message_number >> 0) & 0xff; + message_buf[2] = (message_number >> 8) & 0xff; + message_buf[3] = (message_number >> 16) & 0xff; + message_buf[4] = (message_number >> 24) & 0xff; + send(debug->client_fd, message_buf, 5, 0); +} + +static void process_command(debug_state_t *debug, struct msg_parse_ctx_t *ctx) { + u32 msg_id = *(unsigned int *) &ctx->data[ctx->offset]; + ctx->offset += sizeof(unsigned int); + + u32 command_id = *(unsigned int *) &ctx->data[ctx->offset]; + ctx->offset += sizeof(unsigned int); + + switch (command_id) { + case CMD_NOP: { + send_empty_response(debug, msg_id); + break; + } + + case CMD_RES: { + // Release the threads + bh_arr_each(debug_thread_state_t *, thread, debug->threads) { + // This logic for "how to resume a thread" should be moved + // elsewhere, but now its fine here. + (*thread)->run_count = -1; + sem_post(&(*thread)->wait_semaphore); + } + + send_empty_response(debug, msg_id); + break; + } + + case CMD_BRK: + break; + } +} + +static void process_response(debug_state_t *debug, struct msg_parse_ctx_t *ctx) { +} + +static void process_message(debug_state_t *debug, char *msg, unsigned int bytes_read) { + struct msg_parse_ctx_t ctx; + ctx.data = msg; + ctx.offset = 0; + ctx.bytes_read = bytes_read; + + while (ctx.offset < ctx.bytes_read) { + u8 type = *(u8 *) &ctx.data[ctx.offset]; + ctx.offset++; + + if (type == 0) { + process_command(debug, &ctx); + } else { + process_response(debug, &ctx); + } + } +} + +void *__debug_thread_entry(void * data) { + debug_state_t *debug = data; + debug->debug_thread_running = true; + + // Set up socket listener + // Wait for initial connection/handshake before entering loop. + + debug->listen_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); + + struct sockaddr_un local_addr, remote_addr; + local_addr.sun_family = AF_UNIX; + strcpy(local_addr.sun_path, "/tmp/ovm-debug.0000"); // TODO: Make this dynamic so mulitple servers can exist at a time. + unlink(local_addr.sun_path); // TODO: Remove this line for the same reason. + int len = strlen(local_addr.sun_path) + sizeof(local_addr.sun_family); + bind(debug->listen_socket_fd, (struct sockaddr *)&local_addr, len); + + // + // Currently, there can only be 1 connected debugger instance at a time. + listen(debug->listen_socket_fd, 1); + + len = sizeof(struct sockaddr_un); + debug->client_fd = accept(debug->listen_socket_fd, (void * restrict)&remote_addr, &len); + + close(debug->listen_socket_fd); + + // Disable blocking reads and write in the client socket + // Alternatively, a MSG_DONTWAIT could be used below + fcntl(debug->client_fd, F_SETFL, O_NONBLOCK); + + printf("[INFO ] Client connected\n"); + + char command[4096]; + while (debug->debug_thread_running) { + // + // Try to read commands from the client. + // If an error was returned, bail out of this thread. + i32 bytes_read = recv(debug->client_fd, command, 4096, 0); + if (bytes_read == -1) { + switch (errno) { + case EAGAIN: break; + + case ECONNRESET: + printf("[ERROR] OVM Debugger connection closed by peer.\n"); + debug->debug_thread_running = false; + break; + + default: + printf("[ERROR] OVM Debugger crashed when reading from UNIX socket.\n"); + debug->debug_thread_running = false; + break; + } + } + + // + // If data was returned, process the commands that are inside of it. + if (bytes_read > 0) { + process_message(debug, command, bytes_read); + } + + // + // Check the state of the running program and report any changes. + } + + close(debug->client_fd); + printf("[INFO ] Session closed\n"); + + unlink(local_addr.sun_path); + return NULL; +} diff --git a/src/vm/vm.c b/src/vm/vm.c index 70adeee..6eb5800 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -683,6 +683,24 @@ ovm_value_t ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t tmp_val.u64 = 0; // Check if breakpoints are hit + if (state->debug) { + if (state->debug->run_count == 0) goto should_wait; + + bh_arr_each(u32, bp, state->debug->breakpoints) { + if (*bp == (u32) state->pc) goto should_wait; + } + + goto shouldnt_wait; + + should_wait: + state->debug->state = debug_state_paused; + sem_wait(&state->debug->wait_semaphore); + state->debug->state = debug_state_running; + + shouldnt_wait: + if (state->debug->run_count > 0) state->debug->run_count--; + (void) 0; + } // // Incrementing the program counter here. -- 2.25.1