wineserver ptrace patch

Ove Kaaven ovehk at ping.uio.no
Thu Apr 26 16:10:01 CDT 2001


The Linux kernel always clear the TF flag when doing a PTRACE_CONTINUE, so
in order to keep it, we have to do a PTRACE_SINGLESTEP when it's set. This
is mostly useful for debugging purposes, of course (and only when
single-stepping after a suspend, not when single-stepping after an
exception or breakpoint, so this patch doesn't do anything if
thread->context is set), but I wouldn't be surprised if it turned out that
some very twisted copy protection stuff also needed this.

Alexandre should probably look at this... I think you definitely want to
put the get_thread_context and set_thread_context prototypes in a header,
at least, I'm using those in my gdbremote stuff too...

Log:
Ove Kaaven <ovek at transgaming.com>
Preserve the TF (Trap Flag) when continuing from a ptraced suspend.

Index: server/ptrace.c
===================================================================
RCS file: /cvsroot/winex/wine/server/ptrace.c,v
retrieving revision 1.1.1.3
retrieving revision 1.2
diff -u -r1.1.1.3 -r1.2
--- server/ptrace.c	2000/12/01 08:19:17	1.1.1.3
+++ server/ptrace.c	2001/04/26 02:46:41	1.2
@@ -26,6 +26,9 @@
 #ifndef PTRACE_CONT
 #define PTRACE_CONT PT_CONTINUE
 #endif
+#ifndef PTRACE_SINGLESTEP
+#define PTRACE_SINGLESTEP PT_STEP
+#endif
 #ifndef PTRACE_ATTACH
 #define PTRACE_ATTACH PT_ATTACH
 #endif
@@ -53,6 +56,26 @@
 static int ptrace(int req, ...) { return -1; /*FAIL*/ }
 #endif
 
+/* from context_i386.c */
+extern void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context );
+
+static void ptrace_continue( struct thread *thread, int sig )
+{
+#ifdef __i386__
+    /* The TF bit would be cleared if using PTRACE_CONT,
+       so use PTRACE_SINGLESTEP when we want to keep it */
+    if (!thread->context) {
+        CONTEXT ctx;
+        get_thread_context( thread, CONTEXT_CONTROL, &ctx );
+        if (ctx.EFlags & 0x100) {
+            ptrace( PTRACE_SINGLESTEP, thread->unix_pid, (caddr_t)1, sig );
+            return;
+        }
+    }
+#endif
+    ptrace( PTRACE_CONT, thread->unix_pid, (caddr_t)1, sig );
+}
+
 /* handle a status returned by wait4 */
 static int handle_child_status( struct thread *thread, int pid, int status )
 {
@@ -65,10 +88,10 @@
         {
         case SIGSTOP:  /* continue at once if not suspended */
             if (!thread || !(thread->process->suspend + thread->suspend))
-                ptrace( PTRACE_CONT, pid, (caddr_t)1, sig );
+                ptrace_continue( thread, sig );
             break;
         default:  /* ignore other signals for now */
-            ptrace( PTRACE_CONT, pid, (caddr_t)1, sig );
+            ptrace_continue( thread, sig );
             break;
         }
         return sig;
@@ -168,7 +191,7 @@
 {
     if (!thread->unix_pid) return;
     if (!thread->attached) kill( thread->unix_pid, SIGCONT );
-    else ptrace( PTRACE_CONT, thread->unix_pid, (caddr_t)1, SIGSTOP );
+    else ptrace_continue( thread, SIGSTOP );
 }
 
 /* suspend a thread to allow using ptrace on it */
Index: server/context_i386.c
===================================================================
RCS file: /cvsroot/winex/wine/server/context_i386.c,v
retrieving revision 1.1.1.3
retrieving revision 1.2
diff -u -r1.1.1.3 -r1.2
--- server/context_i386.c	2000/12/01 08:19:13	1.1.1.3
+++ server/context_i386.c	2001/04/15 00:12:05	1.2
@@ -88,7 +88,7 @@
 }
 
 /* retrieve a thread context */
-static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
+void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
 {
     int pid = thread->unix_pid;
     if (flags & CONTEXT_FULL)
@@ -144,7 +144,7 @@
 
 
 /* set a thread context */
-static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
+void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
 {
     int pid = thread->unix_pid;
     if (flags & CONTEXT_FULL)
@@ -206,7 +206,7 @@
 #elif defined(__sun) || defined(__sun__)
 
 /* retrieve a thread context */
-static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
+void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
 {
     int pid = thread->unix_pid;
     if (flags & CONTEXT_FULL)
@@ -257,7 +257,7 @@
 
 
 /* set a thread context */
-static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
+void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
 {
     int pid = thread->unix_pid;
     if (flags & CONTEXT_FULL)
@@ -315,7 +315,7 @@
 #include <machine/reg.h>
 
 /* retrieve a thread context */
-static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
+void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
 {
     int pid = thread->unix_pid;
     if (flags & CONTEXT_FULL)
@@ -366,7 +366,7 @@
 
 
 /* set a thread context */
-static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
+void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
 {
     int pid = thread->unix_pid;
     if (flags & CONTEXT_FULL)





More information about the wine-patches mailing list