[haiku-commits] r39201 - in haiku/trunk: headers/private/kernel src/system/kernel/arch/x86 src/system/kernel/debug

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 30 Oct 2010 13:31:01 +0200 (CEST)

Author: bonefish
Date: 2010-10-30 13:31:01 +0200 (Sat, 30 Oct 2010)
New Revision: 39201
Changeset: http://dev.haiku-os.org/changeset/39201
Ticket: http://dev.haiku-os.org/ticket/6751

Modified:
   haiku/trunk/headers/private/kernel/thread_types.h
   haiku/trunk/src/system/kernel/arch/x86/arch_interrupts.S
   haiku/trunk/src/system/kernel/arch/x86/arch_user_debugger.cpp
   haiku/trunk/src/system/kernel/debug/user_debugger.cpp
Log:
* Added new thread flag THREAD_FLAGS_SINGLE_STEP, which is set to indicate that
  userland single-stepping is enabled for the thread.
* x86_exit_user_debug_at_kernel_entry(): Always store DR6 and DR7 in the CPU
  structure, not only when breakpoints are installed.
* x86_handle_debug_exception(): When encountering a syscall single-step, also
  set the THREAD_FLAGS_DEBUG_THREAD thread flag. Otherwise the
  B_THREAD_DEBUG_STOP would be ignored.
* x86 interrupt handling, DISABLE_BREAKPOINTS():
  - Renamed to STOP_USER_DEBUGGING().
  - Now it also call x86_exit_user_debug_at_kernel_entry() when
    THREAD_FLAGS_SINGLE_STEP is set, so that the debug registers are saved.

Fixes #6751.


Modified: haiku/trunk/headers/private/kernel/thread_types.h
===================================================================
--- haiku/trunk/headers/private/kernel/thread_types.h   2010-10-30 10:33:04 UTC 
(rev 39200)
+++ haiku/trunk/headers/private/kernel/thread_types.h   2010-10-30 11:31:01 UTC 
(rev 39201)
@@ -352,27 +352,29 @@
 #define        THREAD_FLAGS_DEBUG_THREAD                       0x0002
        // forces the thread into the debugger as soon as possible (set by
        // debug_thread())
-#define        THREAD_FLAGS_DEBUGGER_INSTALLED         0x0004
+#define        THREAD_FLAGS_SINGLE_STEP                        0x0004
+       // indicates that the thread is in single-step mode (in userland)
+#define        THREAD_FLAGS_DEBUGGER_INSTALLED         0x0008
        // a debugger is installed for the current team (computed flag for
        // optimization purposes)
-#define        THREAD_FLAGS_BREAKPOINTS_DEFINED        0x0008
+#define        THREAD_FLAGS_BREAKPOINTS_DEFINED        0x0010
        // hardware breakpoints are defined for the current team (computed flag 
for
        // optimization purposes)
-#define        THREAD_FLAGS_BREAKPOINTS_INSTALLED      0x0010
+#define        THREAD_FLAGS_BREAKPOINTS_INSTALLED      0x0020
        // breakpoints are currently installed for the thread (i.e. the 
hardware is
        // actually set up to trigger debug events for them)
-#define        THREAD_FLAGS_64_BIT_SYSCALL_RETURN      0x0020
+#define        THREAD_FLAGS_64_BIT_SYSCALL_RETURN      0x0040
        // set by 64 bit return value syscalls
-#define        THREAD_FLAGS_RESTART_SYSCALL            0x0040
+#define        THREAD_FLAGS_RESTART_SYSCALL            0x0080
        // set by handle_signals(), if the current syscall shall be restarted
-#define        THREAD_FLAGS_DONT_RESTART_SYSCALL       0x0080
+#define        THREAD_FLAGS_DONT_RESTART_SYSCALL       0x0100
        // explicitly disables automatic syscall restarts (e.g. resume_thread())
-#define        THREAD_FLAGS_ALWAYS_RESTART_SYSCALL     0x0100
+#define        THREAD_FLAGS_ALWAYS_RESTART_SYSCALL     0x0200
        // force syscall restart, even if a signal handler without SA_RESTART 
was
        // invoked (e.g. sigwait())
-#define        THREAD_FLAGS_SYSCALL_RESTARTED          0x0200
+#define        THREAD_FLAGS_SYSCALL_RESTARTED          0x0400
        // the current syscall has been restarted
-#define        THREAD_FLAGS_SYSCALL                            0x0400
+#define        THREAD_FLAGS_SYSCALL                            0x0800
        // the thread is currently in a syscall; set/reset only for certain
        // functions (e.g. ioctl()) to allow inner functions to discriminate
        // whether e.g. parameters were passed from userland or kernel

Modified: haiku/trunk/src/system/kernel/arch/x86/arch_interrupts.S
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/arch_interrupts.S    2010-10-30 
10:33:04 UTC (rev 39200)
+++ haiku/trunk/src/system/kernel/arch/x86/arch_interrupts.S    2010-10-30 
11:31:01 UTC (rev 39201)
@@ -98,8 +98,9 @@
                                                   original eax/edx values */   
                        \
        iret
 
-#define DISABLE_BREAKPOINTS()                                                  
                                \
-       testl   $THREAD_FLAGS_BREAKPOINTS_INSTALLED, THREAD_flags(%edi);        
\
+#define STOP_USER_DEBUGGING()                                                  
                                \
+       testl   $(THREAD_FLAGS_BREAKPOINTS_INSTALLED                            
                \
+                               | THREAD_FLAGS_SINGLE_STEP), 
THREAD_flags(%edi);                \
        jz              1f;                                                     
                                                                \
        call    x86_exit_user_debug_at_kernel_entry;                            
                \
   1:
@@ -521,7 +522,7 @@
        // disable breakpoints, if installed
        movl    %dr3, %edi                              // thread pointer
        cli                                                             // 
disable interrupts
-       DISABLE_BREAKPOINTS()
+       STOP_USER_DEBUGGING()
 
        // update the thread's user time
        UPDATE_THREAD_USER_TIME()
@@ -615,7 +616,7 @@
 
        // disable breakpoints, if installed
        cli                                                             // 
disable interrupts
-       DISABLE_BREAKPOINTS()
+       STOP_USER_DEBUGGING()
 
        // update the thread's user time
        UPDATE_THREAD_USER_TIME_PUSH_TIME()

Modified: haiku/trunk/src/system/kernel/arch/x86/arch_user_debugger.cpp
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/arch_user_debugger.cpp       
2010-10-30 10:33:04 UTC (rev 39200)
+++ haiku/trunk/src/system/kernel/arch/x86/arch_user_debugger.cpp       
2010-10-30 11:31:01 UTC (rev 39201)
@@ -571,7 +571,8 @@
        if (struct iframe* frame = i386_get_user_iframe()) {
                struct thread* thread = thread_get_current_thread();
 
-               // set/clear TF in EFLAGS depending on if single stepping is 
desired
+               // set/clear TF in EFLAGS depending on whether single stepping 
is
+               // desired
                if (thread->debug_info.flags & B_THREAD_DEBUG_SINGLE_STEP)
                        frame->flags |= (1 << X86_EFLAGS_TF);
                else
@@ -803,15 +804,17 @@
 {
        struct thread *thread = thread_get_current_thread();
 
-       if (!(thread->flags & THREAD_FLAGS_BREAKPOINTS_INSTALLED))
-               return;
-
        // We need to save the current values of dr6 and dr7 in the CPU 
structure,
        // since in case of a debug exception we might overwrite them before
-       // x86_handle_debug_exception() is called.
+       // x86_handle_debug_exception() is called. Debug exceptions occur when
+       // hitting a hardware break/watchpoint or when single-stepping.
        asm("movl %%dr6, %0" : "=r"(thread->cpu->arch.dr6));
        asm("movl %%dr7, %0" : "=r"(thread->cpu->arch.dr7));
 
+       // The remainder needs only be done, when user breakpoints are 
installed.
+       if (!(thread->flags & THREAD_FLAGS_BREAKPOINTS_INSTALLED))
+               return;
+
        GRAB_THREAD_LOCK();
 
        // disable user breakpoints
@@ -910,7 +913,7 @@
                        if (thread->team != team_get_kernel_team()
                                && i386_get_user_iframe() == NULL) {
                                // TODO: This is not yet fully correct, since a 
newly created
-                               // thread that doesn't have entered userland 
yet also has this
+                               // thread that hasn't entered userland yet also 
has this
                                // property.
                                inKernel = false;
                        }
@@ -937,6 +940,9 @@
                                        atomic_or(&thread->debug_info.flags,
                                                
B_THREAD_DEBUG_NOTIFY_SINGLE_STEP
                                                        | B_THREAD_DEBUG_STOP);
+
+                                       // also set the respective thread flag
+                                       atomic_or(&thread->flags, 
THREAD_FLAGS_DEBUG_THREAD);
                                }
                        }
                }

Modified: haiku/trunk/src/system/kernel/debug/user_debugger.cpp
===================================================================
--- haiku/trunk/src/system/kernel/debug/user_debugger.cpp       2010-10-30 
10:33:04 UTC (rev 39200)
+++ haiku/trunk/src/system/kernel/debug/user_debugger.cpp       2010-10-30 
11:31:01 UTC (rev 39201)
@@ -749,9 +749,10 @@
                if (singleStep) {
                        atomic_or(&thread->debug_info.flags,
                                B_THREAD_DEBUG_SINGLE_STEP);
+                       atomic_or(&thread->flags, THREAD_FLAGS_SINGLE_STEP);
                } else {
                        atomic_and(&thread->debug_info.flags,
-                               ~B_THREAD_DEBUG_SINGLE_STEP);
+                               ~(int32)B_THREAD_DEBUG_SINGLE_STEP);
                }
 
                // unset the "stopped" state
@@ -1282,6 +1283,10 @@
 void
 user_debug_single_stepped()
 {
+       // clear the single-step thread flag
+       struct thread* thread = thread_get_current_thread();
+       atomic_and(&thread->flags, ~(int32)THREAD_FLAGS_SINGLE_STEP);
+
        // prepare the message
        debug_single_step message;
        arch_get_debug_cpu_state(&message.cpu_state);


Other related posts:

  • » [haiku-commits] r39201 - in haiku/trunk: headers/private/kernel src/system/kernel/arch/x86 src/system/kernel/debug - ingo_weinhold