diff --git a/cpu-all.h b/cpu-all.h index 7e77f7656f..d71166c352 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -760,8 +760,10 @@ void cpu_reset_interrupt(CPUState *env, int mask); int cpu_watchpoint_insert(CPUState *env, target_ulong addr); int cpu_watchpoint_remove(CPUState *env, target_ulong addr); +void cpu_watchpoint_remove_all(CPUState *env); int cpu_breakpoint_insert(CPUState *env, target_ulong pc); int cpu_breakpoint_remove(CPUState *env, target_ulong pc); +void cpu_breakpoint_remove_all(CPUState *env); #define SSTEP_ENABLE 0x1 /* Enable simulated HW single stepping */ #define SSTEP_NOIRQ 0x2 /* Do not use IRQ while single stepping */ diff --git a/exec.c b/exec.c index ce2d5d9842..dc13c9bffe 100644 --- a/exec.c +++ b/exec.c @@ -1139,6 +1139,16 @@ int cpu_watchpoint_remove(CPUState *env, target_ulong addr) return -1; } +/* Remove all watchpoints. */ +void cpu_watchpoint_remove_all(CPUState *env) { + int i; + + for (i = 0; i < env->nb_watchpoints; i++) { + tlb_flush_page(env, env->watchpoint[i].vaddr); + } + env->nb_watchpoints = 0; +} + /* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a breakpoint is reached */ int cpu_breakpoint_insert(CPUState *env, target_ulong pc) @@ -1162,6 +1172,17 @@ int cpu_breakpoint_insert(CPUState *env, target_ulong pc) #endif } +/* remove all breakpoints */ +void cpu_breakpoint_remove_all(CPUState *env) { +#if defined(TARGET_HAS_ICE) + int i; + for(i = 0; i < env->nb_breakpoints; i++) { + breakpoint_invalidate(env, env->breakpoints[i]); + } + env->nb_breakpoints = 0; +#endif +} + /* remove a breakpoint */ int cpu_breakpoint_remove(CPUState *env, target_ulong pc) { diff --git a/gdbstub.c b/gdbstub.c index 9a361e3251..1df598dc67 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -962,6 +962,12 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) /* TODO: Make this return the correct value for user-mode. */ snprintf(buf, sizeof(buf), "S%02x", SIGTRAP); put_packet(s, buf); + /* Remove all the breakpoints when this query is issued, + * because gdb is doing and initial connect and the state + * should be cleaned up. + */ + cpu_breakpoint_remove_all(env); + cpu_watchpoint_remove_all(env); break; case 'c': if (*p != '\0') { @@ -985,6 +991,17 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) } gdb_continue(s); return RS_IDLE; + case 'k': + /* Kill the target */ + fprintf(stderr, "\nQEMU: Terminated via GDBstub\n"); + exit(0); + case 'D': + /* Detach packet */ + cpu_breakpoint_remove_all(env); + cpu_watchpoint_remove_all(env); + gdb_continue(s); + put_packet(s, "OK"); + break; case 's': if (*p != '\0') { addr = strtoull(p, (char **)&p, 16);