summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpu-all.h1
-rw-r--r--exec.c17
-rw-r--r--gdbstub.c18
3 files changed, 35 insertions, 1 deletions
diff --git a/cpu-all.h b/cpu-all.h
index 787a054a48..cde8451dd0 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -315,6 +315,7 @@ void cpu_interrupt(CPUState *s, int mask);
int cpu_breakpoint_insert(CPUState *env, uint32_t pc);
int cpu_breakpoint_remove(CPUState *env, uint32_t pc);
+void cpu_single_step(CPUState *env, int enabled);
/* gdb stub API */
extern int gdbstub_fd;
diff --git a/exec.c b/exec.c
index fc0a0cf7af..5ea2163258 100644
--- a/exec.c
+++ b/exec.c
@@ -617,7 +617,8 @@ static void tb_reset_jump_recursive(TranslationBlock *tb)
tb_reset_jump_recursive2(tb, 1);
}
-/* add a breakpoint */
+/* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
+ breakpoint is reached */
int cpu_breakpoint_insert(CPUState *env, uint32_t pc)
{
#if defined(TARGET_I386)
@@ -659,6 +660,20 @@ int cpu_breakpoint_remove(CPUState *env, uint32_t pc)
#endif
}
+/* enable or disable single step mode. EXCP_DEBUG is returned by the
+ CPU loop after each instruction */
+void cpu_single_step(CPUState *env, int enabled)
+{
+#if defined(TARGET_I386)
+ if (env->singlestep_enabled != enabled) {
+ env->singlestep_enabled = enabled;
+ /* must flush all the translated code to avoid inconsistancies */
+ tb_flush();
+ }
+#endif
+}
+
+
/* mask must never be zero */
void cpu_interrupt(CPUState *env, int mask)
{
diff --git a/gdbstub.c b/gdbstub.c
index d255eab6d5..61cb6b1ab5 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -324,6 +324,24 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port)
snprintf(buf, sizeof(buf), "S%02x", ret);
put_packet(buf);
break;
+ case 's':
+ env = cpu_gdbstub_get_env(opaque);
+ if (*p != '\0') {
+ addr = strtoul(p, (char **)&p, 16);
+#if defined(TARGET_I386)
+ env->eip = addr;
+#endif
+ }
+ cpu_single_step(env, 1);
+ ret = main_loop(opaque);
+ cpu_single_step(env, 0);
+ if (ret == EXCP_DEBUG)
+ ret = SIGTRAP;
+ else
+ ret = 0;
+ snprintf(buf, sizeof(buf), "S%02x", ret);
+ put_packet(buf);
+ break;
case 'g':
env = cpu_gdbstub_get_env(opaque);
registers = (void *)mem_buf;