debugging longman dictionary

Laurent Pinchart laurent.pinchart at skynet.be
Tue Mar 19 16:41:19 CST 2002


On Monday 18 March 2002 22:58, Eric Pouech wrote:
> > - it also tries to read/write to the debug registers. this produces an
> > unhandled exception. should be trivial to write an exception handler to
> > support that (right ?)
>
> how does it do the writing exactly ? (I'd suspect more the program wants
> to catch itself a watchpoint)

Here's the C code I wrote from the disassembler output. It might not be 
correct, and might not even compile, but the idea is there.

BOOL ReadWriteDR2 (DWORD command, DWORD * value)
{
	struct {
		WORD limit;
		DWORD * base;
	} idtr;

	void *int0Handler;
	DWORD int0handlerHigh;
	DWORD int0handlerLow;

	DWORD valDR2;
	BOOL  writeDR2;
 
	if ( value == 0 )
		return FALSE;
 
	if ( command == 0x1010 )
	{
		writeDR2 = FALSE;
	}
	else if ( command == 0x1011 )
	{
		writeDR2 = TRUE;
		valDR2 = *value;
	}
	else
		return FALSE;
 
	idtr = reg.IDTR;
	int0Handler = idtr.base[4] & 0xffff0000;
	int0Handler |= idtr.base[0];
 
	int0handlerLow = ((DWORD*)int0Handler)[0];
	int0handlerHigh = ((DWORD*)int0Handler)[1];
 
	/* Install the division by 0 handler:
	   pop %eax
	   pop %eax
	   push %cs
	   push %ebx
	   iret
	 */
	((DWORD*)int0Handler)[0] = 0x530e5858;
	((DWORD*)int0Handler)[1] = 0x000000cf;

	asm ( " movl %%ebx, (%0) " : "=m"(return_label1) );
	asm ( " xorl %%eax, %%eax; div %%eax, %%eax " );
 
return_label1:
	if ( writeDR2 )
	{
		reg.DR2 = valDR2;
	}
	else
	{
		valDR2 = reg.dr2;
	}
 
	idtr = reg.IDTR;
	int0Handler = idtr.base[4] & 0xffff0000;
	int0Handler |= idtr.base[0];

	/* Install the division by 0 handler:
	   pop %eax
	   pop %eax
	   push %cs
	   push %ebx
	   iret
	 */
	((DWORD*)int0Handler)[0] = 0x53515858;
	((DWORD*)int0Handler)[1] = 0x000000cf;

	asm ( " xorl %%ecx, %%ecx; movw %%ecx, %%cs " );
	asm ( " movl %%ebx, (%0) " : "=m"(return_label2) );
	asm ( " xorl %%eax, %%eax; div %%eax, %%eax " );

return_label2:
	((DWORD*)int0Handler)[0] = int0handlerLow;
	((DWORD*)int0Handler)[1] = int0handlerHigh;

	if ( ! writeDR2 )
		*value = valDR2;
 
	return TRUE;
}

The only call to the ReadWriteDR2 function I found in the disassembler output 
is a read call, and the DR2 value is compared with 0xffb31146. Hope this 
helps.

> > bool detect_debugger_from_TIB
> > {
> >         char *pTIB;
> >         asm ( "mov %%fs:0x18, %", "=g"(pTIB) );
> >         if ( pTIB[0x20] == 0 )
> >                 return FALSE;
> >         else
> >                 return TRUE;
> > }
>
> fs:0x18 points in memory to the TEB structure
> and offset 0x20 (from thread.h) says:
> 	20 Process id (win95: debug context)
> so I assume you run it on Win9x, and got it tested this way
> (I wouldn't be surprised that under nt it did test dword 0x64 and/or
> 0x68)

You're right, that function is for Win9x. I haven't disassembled the NT 
function but I can do if needed.

Where can I find some doc about how the fs and gs registers are used ?

Laurent Pinchart



More information about the wine-devel mailing list