Comment 132 for bug 604261

Revision history for this message
In , Stefan-demharter (stefan-demharter) wrote :

(In reply to comment #95)
> Thanks, Stefan, your patch works like a charm! Kernel 2.6.34 + Wine 1.2-rc5,
> now working.
>
> Would you mind explaining a bit what the problem was, how it affected Wine, and
> how your patch fixes it?
> I am very curious :)

Hi Devin,

after I had found the problematic commit I compared the code before the commit with the current code. As I don't know what the code does I did trial-and-error runs on the differences to create a minimal patch solving the issue for me.

I'll show the difference in the problematic code fragment:

The code fragment before the commit:

        if (condition & DR_STEP) {
                if (!user_mode(regs))
                        goto clear_TF_reenable;
        }

        si_code = get_si_code(condition);
        /* Ok, finally something we can handle */
        send_sigtrap(tsk, regs, error_code, si_code);
...
clear_TF_reenable:
        set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
        regs->flags &= ~X86_EFLAGS_TF;
        preempt_conditional_cli(regs);
        return;

The code fragment in the current kernel:

        if ((dr6 & DR_STEP) && !user_mode(regs)) {
                tsk->thread.debugreg6 &= ~DR_STEP;
                set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
                regs->flags &= ~X86_EFLAGS_TF;
        }
        si_code = get_si_code(tsk->thread.debugreg6);
        if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS))
                send_sigtrap(tsk, regs, error_code, si_code);
        preempt_conditional_cli(regs);

Note, that the variable "condition" was renamed to "dr6" in the new code.
As you can see the two "if"-conditions of the first code fragment are equal to the "if"-condition of the second one. But in the first code fragment the program jumps to the end of the function and "get_si_code"/"send_sigtrap" are never called whereas in the second code fragment "get_si_code" is always and "send_sigtrap" may be called.

Furthermore, if you just look at the code after the "if"-case you can see:
"send_sigtrap" is always called in the first code fragment whereas it only is called in the second one if a certain a condition is fulfilled.

My patch more or less restores the old behaviour. I.e. "get_si_code"/"send_sigtrap" are never called in the if-case and are always called in the else-case.

As I said initially, I don't really know what the kernel code does here.
So I can't tell you how and why this affects wine.
Neither can I tell you if this patch fixes the issue in the right way.
Nevertheless I hope this satifies your curiosity a little bit ;)

Maybe a good starting point for further investigations is http://lkml.org/lkml/2009/12/17/462 which has some discussion about the same commit and a similar patch (which doesn't work for me as mentioned in my previous post).

Regards,
Stefan