]> Git Repo - qemu.git/commitdiff
target-i386: fix crash on x86 32bit linux host with hw breakpoint exceptions
authorJason Wessel <[email protected]>
Tue, 26 Jan 2010 22:29:50 +0000 (16:29 -0600)
committerAurelien Jarno <[email protected]>
Sun, 28 Feb 2010 18:20:02 +0000 (19:20 +0100)
If you make use of hw breakpoints on a 32bit x86 linux host, qemu
will segmentation fault when processing the exception.

The problem is that the value of env is stored in $ebp in the op_helper
raise_exception() function, and it can have the wrong value when
calling it from non generated code.

It is possible to work around the problem by restoring the value of
env before calling raise_exception() using a new helper function that
takes (CPUState *) as one of the arguments.

Signed-off-by: Jason Wessel <[email protected]>
Signed-off-by: Aurelien Jarno <[email protected]>
target-i386/exec.h
target-i386/helper.c
target-i386/op_helper.c

index 1fd74fd6953ba010cdf4f23214215a3c91f4c835..4ff3c573cade55fb7180a6bcb1955c6610b5d1bb 100644 (file)
@@ -73,6 +73,7 @@ void do_interrupt_user(int intno, int is_int, int error_code,
                        target_ulong next_eip);
 void QEMU_NORETURN raise_exception_err(int exception_index, int error_code);
 void QEMU_NORETURN raise_exception(int exception_index);
+void QEMU_NORETURN raise_exception_env(int exception_index, CPUState *nenv);
 void do_smm_enter(void);
 
 /* n must be a constant to be efficient */
index 080d2b8c7d35551ee8041d9e9ad8ab720c0db6cf..ce2b5eb346a25b20a1eb6bb0cc9dd8ea8247ea08 100644 (file)
@@ -1862,7 +1862,7 @@ int check_hw_breakpoints(CPUState *env, int force_dr6_update)
 
 static CPUDebugExcpHandler *prev_debug_excp_handler;
 
-void raise_exception(int exception_index);
+void raise_exception_env(int exception_index, CPUState *env);
 
 static void breakpoint_handler(CPUState *env)
 {
@@ -1872,7 +1872,7 @@ static void breakpoint_handler(CPUState *env)
         if (env->watchpoint_hit->flags & BP_CPU) {
             env->watchpoint_hit = NULL;
             if (check_hw_breakpoints(env, 0))
-                raise_exception(EXCP01_DB);
+                raise_exception_env(EXCP01_DB, env);
             else
                 cpu_resume_from_signal(env, NULL);
         }
@@ -1881,7 +1881,7 @@ static void breakpoint_handler(CPUState *env)
             if (bp->pc == env->eip) {
                 if (bp->flags & BP_CPU) {
                     check_hw_breakpoints(env, 1);
-                    raise_exception(EXCP01_DB);
+                    raise_exception_env(EXCP01_DB, env);
                 }
                 break;
             }
index 5eea3221b3a9e2345be44d272cb7aa74e34e5d10..4bb434708caac66d5ade3a68e090705a35256197 100644 (file)
@@ -1351,6 +1351,11 @@ void raise_exception(int exception_index)
     raise_interrupt(exception_index, 0, 0, 0);
 }
 
+void raise_exception_env(int exception_index, CPUState *nenv)
+{
+    env = nenv;
+    raise_exception(exception_index);
+}
 /* SMM support */
 
 #if defined(CONFIG_USER_ONLY)
This page took 0.037967 seconds and 4 git commands to generate.