Mercurial > repos > blastem
comparison gdb_remote.c @ 2397:39a009aea113
Implement watchpoints in gdb remote protocol
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 23 Dec 2023 21:54:33 -0800 |
parents | 3350b3c8faa8 |
children | 8445e814d495 |
comparison
equal
deleted
inserted
replaced
2396:bf4f1a8d1d48 | 2397:39a009aea113 |
---|---|
219 goto not_impl; | 219 goto not_impl; |
220 } | 220 } |
221 break; | 221 break; |
222 case 'Z': { | 222 case 'Z': { |
223 uint8_t type = command[1]; | 223 uint8_t type = command[1]; |
224 char *after_address; | |
225 uint32_t address = strtoul(command+3, &after_address, 16); | |
226 uint32_t kind = strtoul(after_address +1, NULL, 16); | |
224 if (type < '2') { | 227 if (type < '2') { |
225 uint32_t address = strtoul(command+3, NULL, 16); | |
226 insert_breakpoint(context, address, gdb_debug_enter); | 228 insert_breakpoint(context, address, gdb_debug_enter); |
227 bp_def *new_bp = malloc(sizeof(bp_def)); | 229 bp_def *new_bp = malloc(sizeof(bp_def)); |
228 new_bp->next = root->breakpoints; | 230 new_bp->next = root->breakpoints; |
229 new_bp->address = address; | 231 new_bp->address = address; |
230 new_bp->mask = 0xFFFFFF; | 232 new_bp->mask = 0xFFFFFF; |
231 new_bp->type = BP_TYPE_CPU; | 233 new_bp->type = BP_TYPE_CPU; |
232 new_bp->index = root->bp_index++; | 234 new_bp->index = root->bp_index++; |
233 root->breakpoints = new_bp; | 235 root->breakpoints = new_bp; |
234 gdb_send_command("OK"); | 236 gdb_send_command("OK"); |
235 } else { | 237 } else if (type == '2') { |
236 //watchpoints are not currently supported | 238 m68k_add_watchpoint(context, address, kind); |
239 bp_def *new_bp = malloc(sizeof(bp_def)); | |
240 new_bp->next = root->breakpoints; | |
241 new_bp->address = address; | |
242 new_bp->mask = kind; | |
243 new_bp->type = BP_TYPE_CPU_WATCH; | |
244 new_bp->index = root->bp_index++; | |
245 root->breakpoints = new_bp; | |
246 gdb_send_command("OK"); | |
247 } else { | |
248 //read and access watchpoints are not currently supported | |
237 gdb_send_command(""); | 249 gdb_send_command(""); |
238 } | 250 } |
239 break; | 251 break; |
240 } | 252 } |
241 case 'z': { | 253 case 'z': { |
242 uint8_t type = command[1]; | 254 uint8_t type = command[1]; |
255 char *after_address; | |
256 uint32_t address = strtoul(command+3, &after_address, 16); | |
257 uint32_t kind = strtoul(after_address +1, NULL, 16); | |
243 if (type < '2') { | 258 if (type < '2') { |
244 uint32_t address = strtoul(command+3, NULL, 16); | |
245 remove_breakpoint(context, address); | 259 remove_breakpoint(context, address); |
246 bp_def **found = find_breakpoint(&root->breakpoints, address, BP_TYPE_CPU); | 260 bp_def **found = find_breakpoint(&root->breakpoints, address, BP_TYPE_CPU); |
247 if (*found) | 261 if (*found) |
248 { | 262 { |
249 bp_def * to_remove = *found; | 263 bp_def * to_remove = *found; |
250 *found = to_remove->next; | 264 *found = to_remove->next; |
251 free(to_remove); | 265 free(to_remove); |
252 } | 266 } |
253 gdb_send_command("OK"); | 267 gdb_send_command("OK"); |
254 } else { | 268 } else if (type == '2') { |
255 //watchpoints are not currently supported | 269 m68k_remove_watchpoint(context, address, kind); |
270 bp_def **cur = &root->breakpoints; | |
271 while (*cur) | |
272 { | |
273 if ((*cur)->type == BP_TYPE_CPU_WATCH && (*cur)->address == address && (*cur)->mask == kind) { | |
274 break; | |
275 } | |
276 cur = &(*cur)->next; | |
277 } | |
278 if (*cur) { | |
279 bp_def *to_remove = *cur; | |
280 *cur = to_remove->next; | |
281 free(to_remove); | |
282 } | |
283 gdb_send_command("OK"); | |
284 } else { | |
285 //read and access watchpoints are not currently supported | |
256 gdb_send_command(""); | 286 gdb_send_command(""); |
257 } | 287 } |
258 break; | 288 break; |
259 } | 289 } |
260 case 'g': { | 290 case 'g': { |
457 | 487 |
458 void gdb_debug_enter(m68k_context * context, uint32_t pc) | 488 void gdb_debug_enter(m68k_context * context, uint32_t pc) |
459 { | 489 { |
460 dfprintf(stderr, "Entered debugger at address %X\n", pc); | 490 dfprintf(stderr, "Entered debugger at address %X\n", pc); |
461 if (expect_break_response) { | 491 if (expect_break_response) { |
462 gdb_send_command("S05"); | 492 if (context->wp_hit) { |
493 context->wp_hit = 0; | |
494 char reply[128]; | |
495 snprintf(reply, sizeof(reply), "T05watch:%X;", context->wp_hit_address); | |
496 gdb_send_command(reply); | |
497 } else { | |
498 gdb_send_command("S05"); | |
499 } | |
463 expect_break_response = 0; | 500 expect_break_response = 0; |
464 } | 501 } |
465 debug_root *root = find_root(context); | 502 debug_root *root = find_root(context); |
466 if (!root) { | 503 if (!root) { |
467 fatal_error("Could not find debug root for CPU %p\n", context); | 504 fatal_error("Could not find debug root for CPU %p\n", context); |