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);
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) {
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) {
}
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];
// 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)) {
#define CMD_NOP 0
#define CMD_RES 1
#define CMD_BRK 2
+#define CMD_LOC 3
struct msg_parse_ctx_t {
char *data;
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);
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;
}
}
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.
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);
}
}