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