changeset 2397:39a009aea113

Implement watchpoints in gdb remote protocol
author Michael Pavone <pavone@retrodev.com>
date Sat, 23 Dec 2023 21:54:33 -0800
parents bf4f1a8d1d48
children 8445e814d495
files gdb_remote.c
diffstat 1 files changed, 42 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/gdb_remote.c	Sat Dec 23 17:37:57 2023 -0800
+++ b/gdb_remote.c	Sat Dec 23 21:54:33 2023 -0800
@@ -221,8 +221,10 @@
 		break;
 	case 'Z': {
 		uint8_t type = command[1];
+		char *after_address;
+		uint32_t address = strtoul(command+3, &after_address, 16);
+		uint32_t kind = strtoul(after_address +1, NULL, 16);
 		if (type < '2') {
-			uint32_t address = strtoul(command+3, NULL, 16);
 			insert_breakpoint(context, address, gdb_debug_enter);
 			bp_def *new_bp = malloc(sizeof(bp_def));
 			new_bp->next = root->breakpoints;
@@ -232,16 +234,28 @@
 			new_bp->index = root->bp_index++;
 			root->breakpoints = new_bp;
 			gdb_send_command("OK");
+		} else if (type == '2') {
+			m68k_add_watchpoint(context, address, kind);
+			bp_def *new_bp = malloc(sizeof(bp_def));
+			new_bp->next = root->breakpoints;
+			new_bp->address = address;
+			new_bp->mask = kind;
+			new_bp->type = BP_TYPE_CPU_WATCH;
+			new_bp->index = root->bp_index++;
+			root->breakpoints = new_bp;
+			gdb_send_command("OK");
 		} else {
-			//watchpoints are not currently supported
+			//read and access watchpoints are not currently supported
 			gdb_send_command("");
 		}
 		break;
 	}
 	case 'z': {
 		uint8_t type = command[1];
+		char *after_address;
+		uint32_t address = strtoul(command+3, &after_address, 16);
+		uint32_t kind = strtoul(after_address +1, NULL, 16);
 		if (type < '2') {
-			uint32_t address = strtoul(command+3, NULL, 16);
 			remove_breakpoint(context, address);
 			bp_def **found = find_breakpoint(&root->breakpoints, address, BP_TYPE_CPU);
 			if (*found)
@@ -251,8 +265,24 @@
 				free(to_remove);
 			}
 			gdb_send_command("OK");
+		} else if (type == '2') {
+			m68k_remove_watchpoint(context, address, kind);
+			bp_def **cur = &root->breakpoints;
+			while (*cur)
+			{
+				if ((*cur)->type == BP_TYPE_CPU_WATCH && (*cur)->address == address && (*cur)->mask == kind) {
+					break;
+				}
+				cur = &(*cur)->next;
+			}
+			if (*cur) {
+				bp_def *to_remove = *cur;
+				*cur = to_remove->next;
+				free(to_remove);
+			}
+			gdb_send_command("OK");
 		} else {
-			//watchpoints are not currently supported
+			//read and access watchpoints are not currently supported
 			gdb_send_command("");
 		}
 		break;
@@ -459,7 +489,14 @@
 {
 	dfprintf(stderr, "Entered debugger at address %X\n", pc);
 	if (expect_break_response) {
-		gdb_send_command("S05");
+		if (context->wp_hit) {
+			context->wp_hit = 0;
+			char reply[128];
+			snprintf(reply, sizeof(reply), "T05watch:%X;", context->wp_hit_address);
+			gdb_send_command(reply);
+		} else {
+			gdb_send_command("S05");
+		}
 		expect_break_response = 0;
 	}
 	debug_root *root = find_root(context);