http://bugs.winehq.org/show_bug.cgi?id=23323
--- Comment #98 from Stefan stefan.demharter@gmx.net 2010-06-27 19:03:44 --- (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