Dne 03/27/06 v 16:05:15 (+0200), Alexandre Julliard napsal(a):
Petr Tesarik hat@tesarici.cz writes:
No, Windows need not do things like that, because the Windows kernel knows very well, whether it got INT1 or INT3... Some UNIX kernels do not give us that information reliably.
I'm afraid it's not acceptable to do things differently, especially not things like the checking of the previous instruction that may cause extra exceptions. Also stuff like the clearing of DR6 needs a test case, that's something that's visible from the application.
I don't want to cause unnecessary conflicts, so I _have_ written a test case, where Wine does a lot of application-visible things differently. Anyway, I've provided an improvement which only needs to do such things as a fallback on platforms, where the cause of the SIGTRAP cannot be determined easily.
In my opinion, the solution is reasonable because if any application is really interested in the DR6 register (i.e. it is a debugger), it will clear the status register (DR6) anyway, since the processor never clears the bits and unless you clear them manually, the register gets pretty useless.
I wonder why you haven't been bothered by the fact that the current implementation silently drops the TF bit, which is even worse! :O
Petr Tesarik
Petr Tesarik hat@tesarici.cz writes:
In my opinion, the solution is reasonable because if any application is really interested in the DR6 register (i.e. it is a debugger), it will clear the status register (DR6) anyway, since the processor never clears the bits and unless you clear them manually, the register gets pretty useless.
There are applications other than debuggers that care about debug registers, notably copy protection code. We can't afford to do things differently even if they sound reasonable.
I wonder why you haven't been bothered by the fact that the current implementation silently drops the TF bit, which is even worse! :O
I'm sure there are bugs in the current implementation, but that's not a reason for introducing different ones... If you find anything that the current code is doing wrong, please provide a test case demonstrating the bug, and I'll be more than happy to fix it (or to accept a fix if you have one).
Dne 03/27/06 v 16:49:13 (+0200), Alexandre Julliard napsal(a):
Petr Tesarik hat@tesarici.cz writes:
In my opinion, the solution is reasonable because if any application is really interested in the DR6 register (i.e. it is a debugger), it will clear the status register (DR6) anyway, since the processor never clears the bits and unless you clear them manually, the register gets pretty useless.
There are applications other than debuggers that care about debug registers, notably copy protection code. We can't afford to do things differently even if they sound reasonable.
I'm afraid I can't understand you. At first, you're advocating the wrong test for the TF bit by the fact that it's 99.9 % correct and then you're criticizing clearing DR6 which is also 99.9 % correct. Not enough on that, I've provided a patch already which is 100 % correct on most platforms and only 99.9 % correct on the remaining ones.
If you talk about copy protection schemes, I've seen code like this (while debugging self, of course):
pushf pop %eax orl $0x100,%eax push %eax popf
; some code
pushf pop %eax andl ~$0x100,%eax push %eax popf
Now, native Windows will generate EXCEPTION_SINGLE_STEP after the last popf. In Wine you'll get a SIGTRAP (possibly with get_trap_code() == TRAP_x86_TRCTRAP, if TRAP_sig is defined for the platform). This will check the TF bit in context->EFlags. Since this is not set, it will fetch the debug registers and check the lowest 4 bits. These will be zero, so Wine generates an EXCEPTION_BREAKPOINT.
I've already explained in another email that it's not possible to get the correct behavior in any other way than the way I've proposed.
Petr Tesarik