}
bool debug_info_lookup_location(debug_info_t *info, u32 instruction, debug_loc_info_t *out) {
+ if (!info) return false;
+
if (instruction > (u32) bh_arr_length(info->instruction_reducer)) return false;
*out = info->line_info[info->instruction_reducer[instruction]];
return true;
}
bool debug_info_lookup_file(debug_info_t *info, u32 file_id, debug_file_info_t *out) {
+ if (!info) return false;
+
if (file_id > (u32) bh_arr_length(info->files)) return false;
*out = info->files[file_id];
return true;
// 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;
+
bh_arr_each(debug_file_info_t, file, info->files) {
if (!strcmp(file->name, name)) {
*out = *file;
case CMD_RES: {
// Returns: nothing
- // Release the threads
+ u32 thread_id = parse_int(debug, ctx);
+
+ bool resumed_a_thread = false;
+
+ // Release the thread(s)
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);
+ if (thread_id == 0xffffffff || (*thread)->id == thread_id) {
+ // 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);
+ resumed_a_thread = true;
+ }
}
send_response_header(debug, msg_id);
+ send_bool(debug, resumed_a_thread);
break;
}
debug_file_info_t file_info;
bool file_found = debug_info_lookup_file_by_name(debug->info, filename, &file_info);
if (!file_found) {
- send_response_header(debug, msg_id);
- send_bool(debug, false);
- send_int(debug, -1);
- return;
+ goto send_error;
+ }
+
+ if (line > file_info.line_count) {
+ 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;
+ }
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);
+ send_int(debug, 0); // TODO: This should be a unique breakpoint ID
+ break;
+
+ send_error:
+ send_response_header(debug, msg_id);
+ send_bool(debug, false);
+ send_int(debug, -1);
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;
while (ctx.offset < ctx.bytes_read) {
u32 msg_id = *(u32 *) &ctx.data[ctx.offset];
+ assert(msg_id != 0xffffffff);
- if (msg_id != 0xffffffff) {
- process_command(debug, &ctx);
- } else {
- process_response(debug, &ctx);
- }
+ process_command(debug, &ctx);
}
}
//
// Check the state of the running program and report any changes.
+ bh_arr_each(debug_thread_state_t *, thread, debug->threads) {
+ if ((*thread)->state == debug_state_hit_breakpoint) {
+ (*thread)->state = debug_state_paused;
+
+ u32 bp_id = (*thread)->last_breakpoint_hit; // :BreakpointID
+ u32 instr = (*thread)->breakpoints[bp_id];
+
+ debug_loc_info_t loc_info;
+ debug_info_lookup_location(debug->info, instr, &loc_info);
+
+ debug_file_info_t file_info;
+ debug_info_lookup_file(debug->info, loc_info.file_id, &file_info);
+
+ 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);
+ }
+ }
+
bh_arena_clear(&debug->tmp_arena);
}