Last I reported on Warcraft 3 with the ptrace changes in 2.6.10-rc3 is that it made some improvement, but still doesn't work. I'll will describe in detail what I know now.
Since the changes in 2.6.10-rc3, Linus made a very good clean up of ptrace.c and signal.c in arch/i386/kernel. I don't want to necessarily reverse all these changes because they are good changes (ie easier to understand and hack now). So I hacked the kernel to change what is necessary to make the game run again. I have attached the patch against 2.6.10 to show the required changes.
Comments on what I have learned about the 3 ptrace changes (see my original report): #1 ptrace.c
In set_singlestep() and clear_singlestep(), the flag TIF_SINGLESTEP is now set and cleared. In the header file in include/asm-i386/thread_info.h, it seems to indicate to me that it is an internal flag to remember to re enable single-stepping for a thread on returning to the program. While speaking to my brother on this, we believe that this change was done correctly. But this change alone will break the game. I have looked in both wine for PTRACE_SINGLESTEP to see what it does and in the kernel for TIF_SINGLESTEP. Since set/clear TIF_SINGLESTEP causes the problem, I really need more information on everything about TIF_SINGLESTEP.
#2 signal.c - Not single-stepping into signal handlers unless the tracer requests it
Previous to 2.6.9-rc2, my understanding is that a call to setup_frame() would clear the trap flag in preparation for a signal delivery. Roland made a slight tweak to it and an example of it is this: if (regs->eflags & TF_MASK) { if (current->ptrace & PT_PTRACED) { ptrace_notify(SIGTRAP); } else { regs->eflags &= ~TF_MASK; } }
Linus later changed it to: /* * Clear TF when entering the signal handler, but * notify any tracer that was single-stepping it. * The tracer may want to single-step inside the * handler too. */ if (regs->eflags & TF_MASK) { regs->eflags &= ~TF_MASK; if (current->ptrace & PT_DTRACE) ptrace_notify(SIGTRAP); }
In 2.6.10, this new piece of code actually works with Warcraft III. I no longer have to reverse this change. The result is obvious because it makes it so you don't automatically single step into the handler, which wine doesn't really want.
#3 signal.c - Clearing the trap flag if being traced by debugger in setup_sigcontext()
For some reason, Warcraft III doesn't work if it is cleared here. I have no idea if this TF clear is really necessary. However, everything I've read on this seems to indicate to me that this change is important, so I need to find out what this causes to the game.
I captured a log of the seh debug messages because I think this is may be where to look. I also hacked in to display trace messages in wine's dlls/ntdll/signal_i386.c showing eflags and whether TF is cleared in trap_handler() and raise_trap_exception(). I ran the game under 2.6.10 and the modded 2.6.10, to capture the working version, and the failing version. The results are fairly nonrandom and comparable and you can identify differences. Unfortunately, I cannot upload them at the moment because my connection is slow and the files are large. I'll upload it another time.
Jesse