connections work from a remote source
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 2 Aug 2022 00:58:10 +0000 (19:58 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 2 Aug 2022 00:58:10 +0000 (19:58 -0500)
include/ovm_debug.h
src/debug/debug_host.c
src/debug/debug_info_builder.c
src/debug/debug_thread.c [new file with mode: 0644]
src/vm/vm.c

index b58aed29e9a70b020f6a0efb7bbc37593a4c38d3..41a9879a2cff6c8a5f9616a843e6637458d9f005 100644 (file)
@@ -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
index f6f05224a1e351f7b19bef8449fbac5ceb73759a..fafdcfc7acd6a7b68ccabfa56e501375640e5ff4 100644 (file)
@@ -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 <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-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;
-}
index d920af82b181f3cecaeb92bbf4d9ad46762e4d15..28855f5ecb7af3550666025593a94990b9d22cf7 100644 (file)
@@ -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 (file)
index 0000000..8ef3220
--- /dev/null
@@ -0,0 +1,151 @@
+
+#include "ovm_debug.h"
+#include "vm.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+
+
+#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;
+}
index 70adeee05e03f9d62f4e16bc45660540ac6a791a..6eb580068067d1db4e716c657b262a7bdc3265b6 100644 (file)
@@ -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.