initial working version with VS Code
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 10 Aug 2022 18:04:13 +0000 (13:04 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 10 Aug 2022 18:04:13 +0000 (13:04 -0500)
include/ovm_debug.h
src/debug/debug_host.c
src/debug/debug_info.c
src/debug/debug_thread.c

index 453e2f67ca36a019b008c00c318615ba7a67cac8..dbf52c39a03c60af56fc22f01336eb65c7735fb6 100644 (file)
@@ -31,6 +31,8 @@ typedef struct debug_file_info_t {
 typedef struct debug_info_t {
     bh_allocator alloc;
 
+    bool has_debug_info;
+
     // func index -> func info
     bh_arr(debug_func_info_t) funcs;
 
index 48c3eaeba05727f005db1e0c5b21d6dac63dd9b9..31e3f2c8175d7f4f30ca0f6b0bce241b25a2a1a0 100644 (file)
@@ -12,7 +12,7 @@ void debug_host_init(debug_state_t *debug) {
     debug->info = NULL;
 
     debug->threads = NULL;
-    debug->next_thread_id = 0;
+    debug->next_thread_id = 1;
     bh_arr_new(debug->alloc, debug->threads, 4);
 
     debug->listen_socket_fd = 0;
index 5dbc04785eb3302aeeda354e8091b7a8582af197..98743dd6a7b1f0a6c2371c4a1e310656baf1136e 100644 (file)
@@ -5,6 +5,7 @@ void debug_info_init(debug_info_t *info) {
     memset(info, 0, sizeof(*info));
 
     info->alloc = bh_heap_allocator();
+    info->has_debug_info = false;
     bh_arr_new(info->alloc, info->funcs, 16);
     bh_arr_new(info->alloc, info->line_info, 1024);
     bh_arr_new(info->alloc, info->instruction_reducer, 4096);
@@ -25,6 +26,7 @@ void debug_info_free(debug_info_t *info) {
 
 void debug_info_import_file_info(debug_info_t *info, u8 *data, u32 len) {
     u32 offset = 0;
+    info->has_debug_info = true;
 
     i32 count = uleb128_to_uint(data, &offset);
     fori (i, 0, (i32) count) {
@@ -48,6 +50,7 @@ void debug_info_import_file_info(debug_info_t *info, u8 *data, u32 len) {
 
 void debug_info_import_func_info(debug_info_t *info, u8 *data, u32 len) {
     u32 offset = 0;
+    info->has_debug_info = true;
 
     i32 count = uleb128_to_uint(data, &offset);
     fori (i, 0, (i32) count) {
@@ -79,15 +82,18 @@ void debug_info_import_func_info(debug_info_t *info, u8 *data, u32 len) {
 }
 
 bool debug_info_lookup_location(debug_info_t *info, u32 instruction, debug_loc_info_t *out) {
-    if (!info) return false;
+    if (!info || !info->has_debug_info) return false;
 
     if (instruction > (u32) bh_arr_length(info->instruction_reducer)) return false;
-    *out = info->line_info[info->instruction_reducer[instruction]];
+    i32 loc = info->instruction_reducer[instruction];
+    if (loc < 0) return false;
+
+    *out = info->line_info[loc];
     return true;
 }
 
 bool debug_info_lookup_file(debug_info_t *info, u32 file_id, debug_file_info_t *out) {
-    if (!info) return false;
+    if (!info || !info->has_debug_info) return false;
 
     if (file_id > (u32) bh_arr_length(info->files)) return false;
     *out = info->files[file_id];
@@ -98,7 +104,7 @@ bool debug_info_lookup_file(debug_info_t *info, u32 file_id, debug_file_info_t *
 // For now, this is going to compare the strings exactly. In the future, it might be a good
 // to do a levenschtein distance or something, so the full path isn't needed.
 bool debug_info_lookup_file_by_name(debug_info_t *info, char *name, debug_file_info_t *out) {
-    if (!info) return false;
+    if (!info || !info->has_debug_info) return false;
 
     bh_arr_each(debug_file_info_t, file, info->files) {
         if (!strcmp(file->name, name)) {
index beab3c106ecf9e53c4e75e313094af6f948aa9be..5e7716c0f08fb6dac9233c7139b2b06236b36b80 100644 (file)
@@ -11,6 +11,7 @@
 #define CMD_NOP 0
 #define CMD_RES 1
 #define CMD_BRK 2
+#define CMD_LOC 3
 
 struct msg_parse_ctx_t {
     char *data;
@@ -126,11 +127,13 @@ static void process_command(debug_state_t *debug, struct msg_parse_ctx_t *ctx) {
                 goto send_error;
             }
 
-            u32 instr = debug->info->line_to_instruction[file_info.line_buffer_offset + line];
-            if (instr == 0) {
-                // Technically, this condition is not right as it is possible for the first
-                // instruction to have index 0.
-                goto send_error;
+            u32 instr;
+            while ((instr = debug->info->line_to_instruction[file_info.line_buffer_offset + line]) == 0) {
+                line += 1;
+
+                if (line > file_info.line_count) {
+                    goto send_error;
+                }
             }
 
             printf("[INFO ] Setting breakpoint at %s:%d (%xd)\n", filename, line, instr);
@@ -141,13 +144,48 @@ static void process_command(debug_state_t *debug, struct msg_parse_ctx_t *ctx) {
 
             send_response_header(debug, msg_id);
             send_bool(debug, true);
-            send_int(debug, 0);    // TODO: This should be a unique breakpoint ID
+            send_int(debug, 1);    // TODO: This should be a unique breakpoint ID
+            send_int(debug, line);
             break;
 
           send_error:
             send_response_header(debug, msg_id);
             send_bool(debug, false);
             send_int(debug, -1);
+            send_int(debug, 0);
+            break;
+        }
+
+        case CMD_LOC: {
+            u32 thread_id = parse_int(debug, ctx);
+
+            bh_arr_each(debug_thread_state_t *, thread, debug->threads) {
+                if ((*thread)->id == thread_id) {
+                    bool success = true;
+
+                    debug_loc_info_t loc_info;
+                    u32 instr = (*thread)->ovm_state->pc;
+                    while (!debug_info_lookup_location(debug->info, instr, &loc_info)) {
+                        instr++;
+                    }
+
+                    debug_file_info_t file_info;
+                    success = success && debug_info_lookup_file(debug->info, loc_info.file_id, &file_info);
+
+                    if (success) {
+                        send_response_header(debug, msg_id);
+                        send_bool(debug, true);
+                        send_string(debug, file_info.name);
+                        send_int(debug, loc_info.line);
+                        return;
+                    }
+                }
+            }
+
+            send_response_header(debug, msg_id);
+            send_bool(debug, false);
+            send_string(debug, "");
+            send_int(debug, -1);
             break;
         }
     }
@@ -170,7 +208,7 @@ static void process_message(debug_state_t *debug, char *msg, unsigned int bytes_
 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.
     
@@ -245,23 +283,13 @@ void *__debug_thread_entry(void * data) {
                 send_int(debug, 1);
                 send_int(debug, bp_id);
                 send_int(debug, (*thread)->id);
-                send_string(debug, file_info.name);
-                send_int(debug, loc_info.line);
             }
 
             if ((*thread)->state == debug_state_pausing) {
                 (*thread)->state = debug_state_paused;
 
-                debug_loc_info_t loc_info;
-                debug_info_lookup_location(debug->info, (*thread)->ovm_state->pc, &loc_info);
-
-                debug_file_info_t file_info;
-                debug_info_lookup_file(debug->info, loc_info.file_id, &file_info);
-
                 send_int(debug, 2);
                 send_int(debug, (*thread)->id);
-                send_string(debug, file_info.name);
-                send_int(debug, loc_info.line);
             }
         }