ntdll: Fix SIGTRAP handling

Petr Tesarik hat at tesarici.cz
Mon Mar 27 09:15:47 CST 2006


Dne 03/27/06 v 16:49:13 (+0200), Alexandre Julliard napsal(a):
> Petr Tesarik <hat at 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



More information about the wine-devel mailing list