Messages in this thread Patch in this message | | | Date | Wed, 29 Dec 2004 12:40:53 -0700 | From | Jesse Allen <> | Subject | Re: ptrace single-stepping change breaks Wine |
| |
On Wed, 29 Dec 2004 10:53:54 -0800 (PST), Linus Torvalds <torvalds@osdl.org> wrote: > Ok, I don't remember the context from the Wine lists (and it's not clear > from the older emails I was cc'd on), so the "#3 signal.c" change > description is a bit too vague. Jesse, willing to just point to the exact > diff that you need to make Warcraft work for you (and then maybe Thomas > Sailer can verify whether that part is indeed the one that causes him > problems).
I have attached the diff attached in this message for the lkml.
> > The code in question now does > > /* > * Iff TF was set because the program is being single-stepped by a > * debugger, don't save that information on the signal stack.. We > * don't want debugging to change state. > */ > eflags = regs->eflags; > if (current->ptrace & PT_DTRACE) > eflags &= ~TF_MASK; > err |= __put_user(eflags, &sc->eflags); > > and I guess it originally never cleared it. True?
Yes.
> > So does removing the conditional TF clear make everything work again? >
Yes, as long as TIF_SINGLESTEP is not set in set_singlestep(). set_singlestep also sets PT_DTRACE, so as it now is, a call to the set_singlestep function will make this condition true clearing TF when run. So both the conditional TF clear and setting TIF_SINGLESTEP needs to be removed, like I show in the diff. Making these changes returns the code to a 2.6.8-ish resemblence.
For the wine people, I will try to upload the seh debug channel logs as soon as possible.
Jesse diff -u linux/arch/i386/kernel/ptrace.c linux-mod/arch/i386/kernel/ptrace.c --- linux/arch/i386/kernel/ptrace.c 2004-12-09 15:24:07.000000000 -0700 +++ linux-mod/arch/i386/kernel/ptrace.c 2004-12-25 16:09:52.000000000 -0700 @@ -142,7 +142,7 @@ { long eflags; - set_tsk_thread_flag(child, TIF_SINGLESTEP); +// set_tsk_thread_flag(child, TIF_SINGLESTEP); eflags = get_stack_long(child, EFL_OFFSET); put_stack_long(child, EFL_OFFSET, eflags | TRAP_FLAG); child->ptrace |= PT_DTRACE; @@ -153,7 +153,7 @@ if (child->ptrace & PT_DTRACE) { long eflags; - clear_tsk_thread_flag(child, TIF_SINGLESTEP); +// clear_tsk_thread_flag(child, TIF_SINGLESTEP); eflags = get_stack_long(child, EFL_OFFSET); put_stack_long(child, EFL_OFFSET, eflags & ~TRAP_FLAG); child->ptrace &= ~PT_DTRACE; diff -u linux/arch/i386/kernel/signal.c linux-mod/arch/i386/kernel/signal.c --- linux/arch/i386/kernel/signal.c 2004-12-09 15:24:07.000000000 -0700 +++ linux-mod/arch/i386/kernel/signal.c 2004-12-25 16:10:10.000000000 -0700 @@ -299,8 +299,8 @@ * don't want debugging to change state. */ eflags = regs->eflags; - if (current->ptrace & PT_DTRACE) - eflags &= ~TF_MASK; +// if (current->ptrace & PT_DTRACE) +// eflags &= ~TF_MASK; err |= __put_user(eflags, &sc->eflags); err |= __put_user(regs->esp, &sc->esp_at_signal); err |= __put_user(regs->xss, (unsigned int __user *)&sc->ss); | |